来自不同类的 JavaFX 事件处理

标签 java javafx model-view-controller

我查看了与我的问题相似的 stackoverflow 问题,但没有任何帮助。

这是我的问题:

对于一个项目,我正在制作一个纯 Java 的 JavaFX 应用程序,没有 FXML。我有两个类,一个 Controller Controller 类和一个包含 gui 内容 GUI 的类。

Controller 有一个 GUI 类型的成员变量,我试图将事件处理程序分配给 GUI 中的按钮之一,但它似乎不起作用。仅当我尝试在 GUI 类中实现处理程序时,它才有效,但我需要它在 Comtroller 中工作。

Controller的构造函数中如下:

        this.view = view;

        view.addSimpleHandler(new SimpleHandler());

viewGUI 类型,addSimpleHandlerview 的成员函数

SimpleHandlerController 的内部类,它实现 EventHandler 并重写 handle() 函数

public void addSimpleHandler(EventHandler<ActionEvent> e) {
        simpleButton.setOnAction(e);
}

这是我的 GUI 的主要方法和类签名

public class GUI extends Application {
//member variables for the GUI design including simpleButton
    private Button simpleButton;
    public static void main(String[] args) {
        GUI view = new GUI();
        Controller controller = new Controller(view);

        Application.launch(view.getClass(), args);

    }

    public GUI() {
       simpleButton = new Button("Simple button");

       //rest of code is setting up GUI into my panes
    }


    public void start(Stage primaryStage) throws Exception {
        Scene scene = new Scene(mainPane, sceneWidth, sceneHeight);
        //mainPane is a pane that contains simpleButton with a screenwidth and screenHeight
        primaryStage.setTitle("Simple");
        primaryStage.setScene(scene);
        primaryStage.show();

    }

最佳答案

不要手动实例化您的应用程序类。要了解原因,请参阅 the documentation关于 JavaFX 生命周期(重点是我的):

The entry point for JavaFX applications is the Application class. The JavaFX runtime does the following, in order, whenever an application is launched:

  1. Starts the JavaFX runtime, if not already started (see Platform.startup(Runnable) for more information)
  2. Constructs an instance of the specified Application class
  3. Calls the init() method
  4. Calls the start(javafx.stage.Stage) method
  5. Waits for the application to finish, which happens when either of the following occur:
    • the application calls Platform.exit()
    • the last window has been closed and the implicitExit attribute on Platform is true
  6. Calls the stop() method

正如您所看到的,JavaFX 本身将实例化应用程序类,并且它是调用其生命周期方法的实例,这些方法是 init()开始(阶段)停止()。但是,在您的代码中具有以下内容:

public static void main(String[] args) {
    GUI view = new GUI(); // created your own instance
    Controller controller = new Controller(view); // gave controller that instance

    // Launches JavaFX which starts the life-cycle documented above
    Application.launch(view.getClass(), args);
}

您创建自己的GUI实例。该实例不受 JavaFX 管理,这意味着它的 start(Stage) 方法永远不会被调用。当您创建 Controller 实例并向其传递 GUI 实例时,您将 EventHandler 添加到一个从不显示的节点。您看到显示的窗口来自作为调用 Application#launch 的一部分而创建的 GUI 实例,并且该 GUI 实例永远不会与 Controller

对于 JavaFX 应用程序,您应该考虑将 init()start(Stage) 方法作为入口点1。换句话说,在上述生命周期方法之一中创建Controller。尽管我想您可以在构造函数中执行相同的操作2。无论您选择哪一个,请记下哪个线程调用每个方法,记录在 in the same place as the life-cycle 中。 。以下是要点:

  • 应用程序类在 JavaFX 应用程序线程上加载、初始化和构造。
  • init() 方法由 JavaFX-Launcher 线程调用。
  • start(Stage)stop() 方法由 JavaFX 应用程序线程调用。

请记住,某些操作只能在JavaFX应用程序线程上执行。

<小时/>

1。如果需要,您仍然可以在 main 方法中调用 Application#launch 之前执行代码。唯一的限制是代码不应与 JavaFX 直接相关。

2。您的构造函数当前是公共(public)的并且具有零个参数 - 保持这种方式。 JavaFX 要求应用程序类具有公共(public)的无参数构造函数,以便通过反射构造实例。

关于来自不同类的 JavaFX 事件处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58158837/

相关文章:

java - 使用 Java/HttpURLConnection 检索特定 URL 的重定向 URL

java - 对于多个对象,引号中的 JOOQ sql 生成似乎不一致

JavaFX:TableView 单元格像素化 ImageView - 如何撤消转换?

java - 将 FXML 中定义的 AnchorPane 动态添加到选项卡并稍后访问此 Pane 内容

c# - 密码登录异步 MVC C#

java - 如何在单击 TextView 中的文本链接时打开浏览器

java - 如何在 JSP View 中显示实现的自定义 validator 的错误消息?

java - 获取节点上的鼠标位置相对于它的坐标和变换

Spring Boot 返回字符串而不是 View

javascript - ASP.NET Core - 运行多个 Angular 2 应用程序