我有一个主app类和一个fxmlController类,但我纠结于连接/组织(混淆了如何调用它们以及如何组织它们以使GUI连接业务逻辑)业务逻辑和GUI。有人可以告诉我调用以下函数的顺序,还是有人可以帮我打电话给他们?
public void Main() //constructor
public static void main() // our main
public void start() //I don't know what it is, what purpose it has
// and where should be called
//Note: In main function there is a call as following
public void initialize() //I don't know what it is and what purpose it has
public fxmlController() // which function should be called here....
注意:我知道FXMLLoader();
请有人解释
我认为FXML文件及其相应的控制器是一对管理用户界面的。在较大的应用程序中,您可能有几个这样的FXML控制器对,它们组成了用户界面的不同部分。在每对中,FXML文件定义UI的布局,并且控制器定义逻辑(即,它通常处理用户输入等)。
虽然你说你“了解FXMLLoader
”,如果你完全明白,你会真正了解你所问的其他一些事情,所以:
由FXML文件及其控制器定义的用户界面由FXMLLoader
加载到内存中。在最简单的设置中,控制器由FXML文件的根元素中的fx:controller
属性定义。当在load()
上调用FXMLLoader
方法时,它:
fx:controller
属性指定的控制器类的实例@FXML
注释字段的值设置为使用匹配的fx:id
属性定义的元素initialize()
方法。注意那些事件的顺序:在注入@FXML
-annotated字段之前调用构造函数,但之后调用initialize()
方法。这意味着您可以在@FXML
方法中访问(和配置)和initialize()
注释的字段,但不能在构造函数中访问。很常见(至少在简单的应用程序中)不在控制器类中定义任何构造函数,只使用默认值。
您可以根据需要/需要在应用程序中使用尽可能多的FXML /控制器对。每个FXML文件都应该有自己的控制器类。如果您想要定义UI的多个实例,可以根据需要多次加载FXML文件:每次FXMLLoader
都会为您创建一个与您加载的UI元素关联的新控制器实例。
Application
子类(你称之为Main
)代表整个应用程序。每个应用程序应该只有一个这样的类,并且只有一个实例,它是由FX工具包为您创建的。
当您启动FX应用程序(我将在下面描述)时,FX工具包将启动。然后创建一个Application
子类的实例,并调用它的init()
方法(如果你没有定义一个,默认实现什么都不做)。然后启动FX应用程序线程,并在该线程上调用Application
子类实例的start()
方法。
你的start()
方法应该做很少的工作。通常,它会加载您的“主”fxml文件,将生成的UI放在场景中,将场景放在舞台上,然后显示舞台。所有逻辑都将由FXML文件的控制器处理,而不是由Application
子类处理。
在更高级的应用程序中,您可以在init()
方法中启动一些后台服务和/或创建一些数据模型,并使用start()
方法将它们与控制器连接,但上面的想法是基础知识。
实际的启动过程可以通过几种方式实现。如果您使用的是标准的Oracle JRE,那么启动一个Application
子类
java Main
(Main extends Application
)将导致上述过程发生;换句话说,启动FX工具包,创建Main
的实例,调用其init()
方法,并在FX Application Thread上调用start()
方法。
其他环境(特别是IDE)不了解JavaFX启动过程,并期望您正在执行的类具有public static void main(String[] args)
方法,就像任何标准Java应用程序类一样。为了支持这些环境,你的Application
子类通常会定义一个简单地调用main(...)
(从launch(...)
继承的静态方法)的Application
方法。 launch
方法强制FX工具包启动等。它只能在任何应用程序生命周期内调用一次。
所以现在你有类似的东西:
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:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.Label?>
<?import java.util.ArrayList?>
<VBox xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.example.MyController">
<Label fx:id="label1"/>
<Label fx:id="label2"/>
</VBox>
和控制器
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");
}
}
控制器绑定在您的fxml文件中或您第一次调用主视图的位置。
因此,您可以使用xml中的fx:controller
属性或启动器中的FXMLLoader#setController()
方法。