【问题标题】:Perform action on showing FXML with JavaFX 8使用 JavaFX 8 对显示 FXML 执行操作
【发布时间】:2014-09-27 00:53:59
【问题描述】:

我正在构建一个具有多个屏幕的 JavaFX 应用程序,因此具有多个 FXML 文件及其控制器。当应用程序启动所有 FXML 文件时,控制器的初始化方法已经完成。

我有一个锁屏,用户需要输入密码才能进入下一个屏幕。当密码正确时,检索员工姓名并加载主菜单屏幕。

我想将用户名传递给主菜单屏幕中的标签,但我不能使用控制器的初始化方法,因为它已经被调用了。

有没有办法在显示 FXML 屏幕时执行操作,使我能够在控制器之间传递字符串?

非常感谢任何帮助!

ps。如果您想查看代码,请在下方评论。

编辑(为了更好地理解)

您可以在下面找到代码:

Main.java

public class Main extends Application {

public static String screen1ID = "loginscherm";
public static String screen1File = "Lockscreen.fxml";
public static String screen2ID = "mainmenu";
public static String screen2File = "MainMenu.fxml";
//public static String screen3ID = "screen3";
//public static String screen3File = "Screen3.fxml";
public static Functions databaseConnection;

@Override
public void start(Stage stage) throws Exception {

    databaseConnection = new Functions();
    databaseConnection.DB_Connect();

    octocash.GUI_Screens.ScreensController mainContainer = new octocash.GUI_Screens.ScreensController();
    mainContainer.loadScreen(Main.screen1ID, Main.screen1File);
    mainContainer.loadScreen(Main.screen2ID, Main.screen2File);

    mainContainer.setScreen(Main.screen1ID);

    Group root = new Group(); //als je meerdere vensters in moet laden
    root.getChildren().addAll(mainContainer);
    Scene scene = new Scene(root);
    stage.setScene(scene);
    stage.setFullScreen(true); //full screen without borders (no program menu bars)
    stage.setFullScreenExitHint(""); //Don't show "Press ESC to exit full screen"
    //stage.setFullScreenExitKeyCombination(KeyCombination.NO_MATCH); //NIET AANZETTEN VOOR JE IETS ANDERS GEMAAKT HEBT ZODAT JE ERUIT KUNT
    stage.show();
}

/**
 * @param args the command line arguments
 */
public static void main(String[] args) {
    launch(args);
}   
}

LockscreenController.java

public class LockscreenController implements Initializable, ControlledScreen {

ScreensController myController;

@FXML
private PasswordField passwordField;
public FlowPane mainContent;
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();

@Override
public void initialize(URL url, ResourceBundle rb) {
    mainContent.setPrefSize(screenSize.getWidth(), screenSize.getHeight());
}

public void setScreenParent(ScreensController screenParent){
    myController = screenParent;
}

@FXML
private void goToMainMenu(){
   myController.setScreen(octocash.Main.screen2ID); 
}

public static String employeeName;
public static String employeeIsAdmin;

@FXML
private void checkPassword(ActionEvent event){
   String input = passwordField.getText();
   String needsToBeChecked;
   needsToBeChecked = (new octocash.Functions()).hashPassword(input);
   String[][] employeeInfo = octocash.Main.databaseConnection.getData("some_query", Arrays.asList("naam","isAdmin"));

   if(employeeInfo[0][0] != null) {
       employeeName = employeeInfo[0][0];
       employeeIsAdmin = employeeInfo[0][1];
       goToMainMenu();
       passwordField.setText("");
   }
   else{
       passwordField.setText("");
   } 
}   
}

MainMenuController.java

public class MainMenuController implements Initializable, ControlledScreen {

ScreensController myController;

public FlowPane mainContent;
public ToolBar toolBar;
public Region spacerToolbar;
public HBox buttonHolder;
public Button exitButton;
public Label currentlyLoggedIn;
public Button testButton;
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();

@Override
public void initialize(URL url, ResourceBundle rb) {
    mainContent.setPrefSize(screenSize.getWidth(), screenSize.getHeight());
    toolBar.setMinWidth(screenSize.getWidth());
    buttonHolder.setHgrow(spacerToolbar, Priority.ALWAYS); //Align buttonHolder to the right
}

public void setScreenParent(ScreensController screenParent){
    myController = screenParent;
}

@FXML
private void exitApplication(){
    Stage stage = (Stage) exitButton.getScene().getWindow();
    stage.close();
} 
}

现在:我想从 LockscreenController 获取 employeeName 的值并将其发送到 MainMenuController,而不使用初始化方法。

【问题讨论】:

  • 也许mainMenuScreenController.setUserLabel(loggedInUserName);
  • 你知道控制器之间是如何传输数据的吗?
  • @UlukBiy 不仅用户名需要,以后其他字符串变量也需要。
  • @ItachiUchiha 不,这正是我想知道的。
  • @bashoogzaad 请通过Multiple FXML with Controllers, share objectPassing Parameters JavaFX FXML,如果您仍有疑问,请联系我们

标签: java javafx-8 fxml


【解决方案1】:

你必须找到一种方法来链接它们之间的控制器,或者只是必须能够访问其他控制器的控制器,你必须实现一个类似的方法

mainController.refreshMainMenuLabel(User user)

所以当用户登录时,该控制器将调用 mainController 的 refreshMainMenuLabel

编辑

我会给你一个带有 2 个控制器的例子

第一次定义 AppContext

 public static class AppContext{

            //you can add the controllers by their variables 
            private Controller1 test1;
            private Controller2 test2;

            //or from a list which will require handling , but it will be more dynamic
              private List<Controller> controllers;
            private static AppContext context=null;
            //You make the constructor private so its really a sigleton ,
            //cause noone can access it from outer package
            private AppContext()
            {

            }

           public static AppContext getAppContext(){
               if(context==null)
                      context=new AppContext();
               return context;
           }

           public void setController1(Controller1 e)
           {
               test1=e;
           }

           public void setController2(Controller2 e)
           {
               test2=e;
           }

           public Controller1 getController1()
           {
               return test1;
           }

           public Controller2 getController2()
           {
               return test2;
           }  

        }

所以这些方法可以像 AppContext.getAppContext().getController1() 一样从应用程序的任何地方调用,因为 getAppcontext 是静态的, 如果您有任何问题,请告诉我

【讨论】:

  • 感谢您的评论,但我不知道如何链接控制器。我已经知道我可能需要实施的方法。
  • 最简单但不是最好的方法是将它们传递给控制器​​的构造函数,或者您可以创建一个单例类,从中设置和获取活动控制器,该类将可供所有人使用项目中的其他类,以便您可以在运行时引用所有控制器
  • 你能举例说明如何创建这样一个单例类,以及在哪里定义它吗?
  • 感谢您的示例!我现在可以在第一个控制器的 AppContext 中设置一个变量的值,但是我无法在第二个控制器中获取它,因为我不能将它放在初始化方法中,因为它已经被执行了。 initialize 方法已经执行,因为所有的屏幕都是在应用程序启动时加载的,并放在 StackPane 中。我用这个:youtube.com/watch?v=5GsdaZWDcdY
  • init 方法用于初始化框架,当用户登录时,您将不会再次初始化框架,因为它已经初始化,但您将从其控制器调用 loginUser() 方法,该方法将刷新已经初始化的帧的内容
猜你喜欢
  • 1970-01-01
  • 2020-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-11
  • 2017-11-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多