Java 如何将FX控制器与主应用程序连接
我有一个主应用程序类和一个fxmlController类,但我陷入了连接/组织(不知道如何调用它们以及如何组织它们以使GUI连接业务逻辑)业务逻辑和GUI的困境。有人能告诉我以下函数的调用顺序吗?或者有人能告诉我应该如何调用它们吗 主要类别: fxmlController类:Java 如何将FX控制器与主应用程序连接,java,user-interface,model-view-controller,javafx,fxml,Java,User Interface,Model View Controller,Javafx,Fxml,我有一个主应用程序类和一个fxmlController类,但我陷入了连接/组织(不知道如何调用它们以及如何组织它们以使GUI连接业务逻辑)业务逻辑和GUI的困境。有人能告诉我以下函数的调用顺序吗?或者有人能告诉我应该如何调用它们吗 主要类别: fxmlController类: 注意:我知道fxmloader()请有人解释一下控制器绑定在您的fxml文件中,或者您第一次调用主视图的位置 因此,您可以使用xml中的fx:controller属性或启动器中的fxmloader#setControlle
注意:我知道
fxmloader()代码>请有人解释一下控制器绑定在您的fxml文件中,或者您第一次调用主视图的位置
因此,您可以使用xml中的fx:controller
属性或启动器中的fxmloader#setController()
方法 我认为FXML文件和相应的控制器是一对,用于管理用户界面。在更大的应用程序中,您可能有几个这样的FXML控制器对,它们构成用户界面的不同部分。在每一对中,FXML文件定义UI的布局,控制器定义逻辑(即,它通常处理用户输入等)
虽然您说您“了解fxmloader
”,但如果您完全理解这一点,您实际上会理解您询问的其他一些事情,因此:
由FXML文件及其控制器定义的用户界面由FXMLLoader
加载到内存中。在最简单的设置中,控制器由FXML文件根元素中的fx:controller
属性定义。在FXMLLoader
上调用load()
方法时,它:
加载FXML文件
通过调用其无参数构造函数,创建由fx:controller
属性指定的控制器类的实例
将控制器中任何带注释的@FXML
字段的值设置为使用匹配的fx:id
属性定义的元素
注册映射到控制器中方法的任何事件处理程序
调用控制器上的initialize()
方法(如果有)
请注意这些事件的顺序:在注入带注释的@FXML
字段之前调用构造函数,但是在注入之后调用initialize()
方法。这意味着您可以在initialize()
方法中访问(和配置)和@FXML
-注释字段,但不能在构造函数中。不在控制器类中定义任何构造函数而只使用默认值是很常见的(至少在简单的应用程序中)
您可以在应用程序中根据需要/需要拥有任意多个FXML/控制器对。每个FXML文件都应该有自己的控制器类。如果需要FXML文件定义的UI的多个实例,可以根据需要多次加载FXML文件:每次FXMLLoader
都会为您创建一个与加载的UI元素关联的新控制器实例
Application
子类(您称之为Main
)代表整个应用程序。每个应用程序应该只有一个这样的类,并且只有一个由FX工具箱为您创建的实例
启动FX应用程序(我将在下面介绍)时,FX工具包将启动。然后创建应用程序
子类的一个实例,并调用其init()
方法(如果未定义一个,则默认实现不做任何操作)。然后启动FX应用程序线程,并在该线程上调用子类实例的start()
方法
您的start()。通常,它会加载“主”fxml文件,将生成的UI放在场景中,将场景放在舞台上,然后显示舞台。所有逻辑将由FXML文件的控制器处理,而不是由应用程序
子类处理
在更高级的应用程序中,您可以在init()
方法中启动一些后台服务和/或创建一些数据模型,并在start()
方法中将它们与控制器连接,但以上思想是基础
实际的启动过程有两种方式。如果您使用的是标准的Oracle JRE,则使用
java Main
(其中,Main扩展应用程序
)将导致上述过程发生;换句话说,启动FX工具箱,创建Main
的实例,调用其init()
方法,并在FX应用程序线程上调用其start()
方法
其他环境(特别是IDE)不知道JavaFX启动过程,并且希望您正在执行的类具有公共静态void main(String[]args)
方法,就像任何标准Java应用程序类一样。为了支持这些环境,您的应用程序
子类通常定义一个main(…)
方法,该方法只调用launch(…)
(从应用程序继承的静态方法)。launch
方法强制FX toolkit启动,等等。在任何应用程序生命周期中只能调用一次
现在你有了这样的东西:
package com.example ;
// imports...
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
// just load fxml file and display it in the stage:
FXMLLoader loader = new FXMLLoader(getClass().getResource("mainUI.fxml"));
Parent root = loader.load();
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
// main method to support non-JavaFX-aware environments:
public static void main(String[] args) {
// starts the FX toolkit, instantiates this class,
// and calls start(...) on the FX Application thread:
launch(args);
}
}
然后您将拥有mainUI.fxml:
和控制器
package com.example ;
// imports...
public class MyController {
@FXML
private Label label1 ;
@FXML
private Label label2 ;
// called by the FXML loader after the labels declared above are injected:
public void initialize() {
// do initialization and configuration work...
// trivial example, could also be done directly in the fxml:
label1.setText("Foo");
label2.setText("Bar");
}
}
解释JavaFX机器的极好答案,谢谢@詹姆斯,完美的解释。我试图制作一种游戏,在画布上绘制简单的几何图形,并根据某种算法移动。你能告诉我是应该在Main的init()中还是在Controller类中编写这段代码(在画布上绘制和移动逻辑)吗?谢谢你!根据从处理用户事件的控制器类接收的参数,在视图类的画布上绘制。移动逻辑会影响数据的状态,因此它应该在模型类方法中。@T
package com.example ;
// imports...
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
// just load fxml file and display it in the stage:
FXMLLoader loader = new FXMLLoader(getClass().getResource("mainUI.fxml"));
Parent root = loader.load();
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
// main method to support non-JavaFX-aware environments:
public static void main(String[] args) {
// starts the FX toolkit, instantiates this class,
// and calls start(...) on the FX Application thread:
launch(args);
}
}
package com.example ;
// imports...
public class MyController {
@FXML
private Label label1 ;
@FXML
private Label label2 ;
// called by the FXML loader after the labels declared above are injected:
public void initialize() {
// do initialization and configuration work...
// trivial example, could also be done directly in the fxml:
label1.setText("Foo");
label2.setText("Bar");
}
}