kha*_*han 6 java model-view-controller user-interface javafx fxml
我有一个主应用程序类和一个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
Run Code Online (Sandbox Code Playgroud)
public void initialize() //I don't know what it is and what purpose it has
public fxmlController() // which function should be called here....
Run Code Online (Sandbox Code Playgroud)
Jam*_*s_D 46
我认为FXML文件及其相应的控制器是一对管理用户界面的.在较大的应用程序中,您可能有几个这样的FXML控制器对,它们组成了用户界面的不同部分.在每对中,FXML文件定义UI的布局,并且控制器定义逻辑(即,它通常处理用户输入等).
虽然你说你"了解FXMLLoader
",但如果你完全明白,你实际上会理解你提到的其他一些事情,所以:
由FXML文件及其控制器定义的用户界面由a加载到内存中FXMLLoader
.在最简单的设置中,控制器由fx:controller
FXML文件的根元素中的属性定义.当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
Run Code Online (Sandbox Code Playgroud)
(何处Main extends Application
)将导致上述过程发生; 换句话说,启动FX工具包,Main
创建一个实例,init()
调用其方法,并start()
在FX Application Thread上调用它的方法.
其他环境(特别是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);
}
}
Run Code Online (Sandbox Code Playgroud)
然后你会有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>
Run Code Online (Sandbox Code Playgroud)
和控制器
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");
}
}
Run Code Online (Sandbox Code Playgroud)