如何将fx控制器与主应用程序连接

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)

fxmlController类

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:controllerFXML文件的根元素中的属性定义.当load()调用该方法时FXMLLoader,它:

  1. 加载FXML文件
  2. fx:controller通过调用其无参数构造函数,创建属性指定的控制器类的实例
  3. @FXML将控制器中任何带注释的字段的值设置为使用匹配fx:id属性定义的元素
  4. 注册映射到控制器中的方法的任何事件处理程序
  5. initialize()如果有,则调用控制器上的方法.

注意这些事件的顺序:构造函数被调用之前@FXML-annotated领域注入,但initialize()方法后调用.这意味着您可以@FXMLinitialize()方法中访问(和配置)和注释的字段,但不能在构造函数中访问.很常见(至少在简单的应用程序中)不要在控制器类中定义任何构造函数,只是使用默认值.

您可以根据需要/需要在应用程序中使用尽可能多的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)

  • 解答JavaFX机器的优秀答案,谢谢! (2认同)