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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33881046/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 15:06:50  来源:igfitidea点击:

How to connect FX controller with main app

javauser-interfacemodel-view-controllerjavafxfxml

提问by khan

I have a main app class and a fxmlController class but I am entangled in connecting/organizing(confused how these are called and how I should organize them to make the GUI connected business logic) business logic and GUI. Can someone please tell the order in which following function are called or can anyone help how I should call them?

我有一个主要的应用程序类和一个 fxmlController 类,但我纠结于连接/组织(困惑如何调用它们以及我应该如何组织它们以制作 GUI 连接的业务逻辑)业务逻辑和 GUI。有人可以告诉我调用以下函数的顺序,或者任何人都可以帮助我如何调用它们?

Main class:

主要类:

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

fxmlController class:

fxmlController 类:

public void initialize()  //I don't know what it is and what purpose it has
public fxmlController()   // which function should be called here....

NOTE: I know about FXMLLoader();please someone explain

注意:我知道FXMLLoader();请有人解释一下

采纳答案by James_D

I think of an FXML file and its corresponding controller as a pair that manage the user interface. In larger applications you might have several such FXML-controller pairs that make up different parts of the user interface. Within each pair, the FXML file defines the layout of the UI, and the controller defines the logic (i.e. it typically processes user input, etc).

我认为 FXML 文件及其相应的控制器是管理用户界面的一对。在较大的应用程序中,您可能有几个这样的 FXML 控制器对,它们构成了用户界面的不同部分。在每一对中,FXML 文件定义了 UI 的布局,控制器定义了逻辑(即它通常处理用户输入等)。

While you said you "know about FXMLLoader", if you understand that fully you would actually understand some of the other things you asked about, so:

虽然你说你“知道FXMLLoader”,但如果你完全理解,你实际上会理解你问的其他一些事情,所以:

The user interface defined by an FXML file and its controller is loaded into memory by an FXMLLoader. In the simplest setup, the controller is defined by a fx:controllerattribute in the root element of the FXML file. When the load()method is called on the FXMLLoader, it:

由 FXML 文件定义的用户界面及其控制器通过FXMLLoader. 在最简单的设置中,控制器由fx:controllerFXML 文件根元素中的属性定义。当在load()上调用该方法时FXMLLoader,它:

  1. Loads the FXML file
  2. Creates an instance of the controller class specified by the fx:controllerattribute, by calling its no-argument constructor
  3. Sets the value of any @FXML-annotated fields in the controller to the elements defined with matching fx:idattributes
  4. Registers any event handlers mapping to methods in the controller
  5. Calls the initialize()method on the controller, if there is one.
  1. 加载 FXML 文件
  2. fx:controller通过调用其无参数构造函数,创建由属性指定的控制器类的实例
  3. @FXML将控制器中任何带注释的字段的值设置为使用匹配fx:id属性定义的元素
  4. 注册映射到控制器中方法的任何事件处理程序
  5. 调用initialize()控制器上的方法(如果有)。

Notice the order of those events: the constructor is called beforethe @FXML-annotated fields are injected, but the initialize()method is called after. This means you can access (and configure) and @FXML-annotated fields in the initialize()method, but not in the constructor. It is quite common (at least in simple applications) not to define any constructor in the controller classes and just to use the default.

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

You can have as many FXML/controller pairs in your application as you need/want. Each FXML file should have its own controller class. You can load an FXML file as many times as you need if you want multiple instances of the UI it defines: each time the FXMLLoaderwill create a new controller instance for you that is associated with the UI element you loaded.

您可以根据需要/希望在应用程序中拥有任意数量的 FXML/控制器对。每个 FXML 文件都应该有自己的控制器类。如果您想要它定义的 UI 的多个实例,您可以根据需要多次加载 FXML 文件:每次FXMLLoader都会为您创建一个与您加载的 UI 元素相关联的新控制器实例。

The Applicationsubclass (you called it Main) represents the entire application. You should have only one such class per application and only one instance of it, which is created for you by the FX toolkit.

Application子类(你叫它Main)代表整个应用程序。每个应用程序应该只有一个这样的类和它的一个实例,它是由 FX 工具包为您创建的。

When you start a FX application (which I'll describe below), the FX toolkit is started. Then an instance of your Applicationsubclass is created, and its init()method is called (if you don't define one, the default implementation does nothing). The FX Application Thread is then started and the Applicationsubclass instance's start()method is called on that thread.

当您启动一个 FX 应用程序(我将在下面描述)时,FX 工具包就会启动。然后你的Application子类的一个实例被创建,它的init()方法被调用(如果你没有定义一个,默认实现什么都不做)。然后启动 FX 应用程序线程,并在该线程上调用Application子类实例的start()方法。

Your start()method should do pretty minimal work. Typically it will load your "main" fxml file, place the resulting UI in a scene, put the scene in the stage, and show the stage. All the logic will be handled by the controller for the FXML file, not by the Applicationsubclass.

你的start()方法应该做的工作很少。通常,它会加载您的“主”fxml 文件,将生成的 UI 放置在场景中,将场景放入舞台并显示舞台。所有逻辑将由控制器处理 FXML 文件,而不是由Application子类处理。

In more advanced applications, you might start some background services and/or create some data models in your init()method, and connect them with the controller in the start()method, but the ideas above are the basics.

在更高级的应用程序中,你可能会在你的init()方法中启动一些后台服务和/或创建一些数据模型,并将它们与start()方法中的控制器连接起来,但上面的想法是基础。

The actual startup process can happen in a couple of ways. If you are using the standard Oracle JRE, then launching an Applicationsubclass with

实际的启动过程可以通过几种方式发生。如果您使用的是标准 Oracle JRE,则使用以下命令启动Application子类

java Main

(where Main extends Application) will cause the process above to happen; in other words the FX toolkit is started, an instance of Mainis created, its init()method is called, and it's start()method is called on the FX Application Thread.

(where Main extends Application) 将导致上述过程发生;换句话说,FX 工具包启动,Main创建一个实例,init()调用它的start()方法,并在 FX 应用线程上调用它的方法。

Other environments (particularly IDEs) are not aware of the JavaFX startup process, and expect the class you are executing to have a public static void main(String[] args)method, like any standard Java application class. To support these environments, it is common for your Applicationsubclass to define a main(...)method which simply calls launch(...)(a static method inherited from Application). The launchmethod forces the FX toolkit to start, etc. It can only be called once during any application lifetime.

其他环境(尤其是 IDE)不知道 JavaFX 启动过程,并期望您正在执行的类具有public static void main(String[] args)方法,就像任何标准 Java 应用程序类一样。为了支持这些环境,您的Application子类通常定义一个main(...)简单调用的方法launch(...)(从 继承的静态方法Application)。该launch方法强制 FX 工具包启动等。它只能在任何应用程序生命周期内调用一次。

So now you have something like:

所以现在你有类似的东西:

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); 
    }
}

Then you would have mainUI.fxml:

然后你会有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>

and the controller

和控制器

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");
    }
}

回答by antoniodvr

The controller is binded in you fxml file or where you call the main view for the first time.

控制器绑定在您的 fxml 文件中或您第一次调用主视图的位置。

So you can use the fx:controllerattribute in the xml or the FXMLLoader#setController()method from your launcher.

因此,您可以使用fx:controllerxml 中的属性或FXMLLoader#setController()启动器中的方法。