我想要一个登录页面(我有工作),然后进入一个新场景(我还没有工作)。
然后我希望这个场景有你可以点击的项目。每个项目打开另一个场景/窗口。但是您可以根据需要打开任意数量。它们包含不同的数据,但相同的 fxml/scene。
这可能吗?
答案 0 :(得分:0)
是的,这是可能的。它需要您为场景创建一个控制器,然后为该场景的每个新实例创建该控制器对象的新实例。我认为它也需要每次都通过一个新阶段。
编辑: 未能为场景的每个新实例创建新的控制器实例意味着有可能从另一个窗口中的打开场景覆盖一个窗口中打开场景中的数据窗口。
如果您不熟悉 JavaFX,我将提供一些创建新视图的示例。这个问题主要是关于这样做的方法。
假设您遵循 MVC 模式,您的项目的结构可能类似于:
编辑:更正了 FXMLLoader 的不当使用
MainApp.java
import java.io.IOException;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.stage.Modality;
import javafx.stage.Stage;
import Controller.LoginController;
public class Main
extends Application
{
public static void main(String[] args)
{
launch(args);
}
@Override
public void start(Stage stage) throws Exception
{
try {
FXMLLoader loader = new FXMLLoader(Main.class.getResource("/View/Login.fxml"));
Parent root = loader.load();
stage.setScene(new Scene(root));
LoginController loginController = loader.getController();
// Pass this stage by calling the controller's stage setter.
// Conversely we could call a singleton class here to
// give us a stage object that we can re-use many times
loginController.setStage(stage);
stage.initStyle(StageStyle.UNIFIED);
stage.setResizable(false);
stage.getIcons().add(new Image("Resources/icon.png"));
stage.setTitle("");
stage.centerOnScreen();
stage.show();
} catch (IOException ex) {
// exception handling
}
}
}
登录控制器.java
import java.net.URL;
import java.io.IOException;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.event.EventHandler;
import javafx.scene.control.Button;
import javafx.stage.Modality;
import javafx.stage.Stage;
import Controller.MainController;
public class LoginController implements Initializable
{
@FXML
private Button loginButton;
private Stage stage;
public LoginController() {}
@Override
public void initialize(URL url, ResourceBundle rb) {
loginButton.addEventHandler(MouseEvent.MOUSE_CLICKED, (e) -> {
doLogin();
});
}
@FXML
private void doLogin() {
// handle login
showMainApplicationView();
}
@FXML
private void showMainApplicationView() {
try {
loader = new FXMLLoader(LoginController.class.getResource("View/mainView.fxml"));
Parent root = (Parent) loader.load();
MainController mainController = new MainController();
loader.setController(mainController);
mainController.setStage(new Stage());
stage.initModality(m);
stage.setResizable(isResizable);
stage.getIcons().add(new Image("Resources/icon.png"));
stage.setTitle(title);
stage.setScene(new Scene(root));
return stage;
} catch (IOException e) {
// exception handling
}
}
@FXML
public void setStage(Stage stage) {
this.stage = stage;
}
}
MainController.java
import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.stage.Stage;
public class LoginController implements Initializable
{
public LoginController() {}
@Override
public void initialize(URL url, ResourceBundle rb) {}
@FXML
private void showSubview() {
/* Same code as the prior examples for launching a new view
* It will work for creating as many new "windows" of the same
* view as you desire. If you need to pass different types of
* data to each view you can use a DAO model, or some kind of
* "Instance" object that works for sending/receiving data to/from
* the subview from this class.
*/
}
@FXML
public void setStage(Stage stage) {
this.stage = stage;
}
}
如果您想多次重复使用一个舞台并以不同的深度进入子视图,我建议使用 Singleton 类。
StageHolder.java
import javafx.stage.Stage;
public final StageHolder
{
private Stage stage;
private final static StageHolder INSTANCE = new StageHolder();
private StageHolder() {}
public static StageHolder getInstance() {
return INSTANCE;
}
public Stage getStage() {
return this.stage;
}
// you can omit this setter if you only want to re-use a single stage over and over.
public void setStage(Stage stage) {
this.stage = stage;
}
}