使用 JavaFX 打开多个窗口

Ser*_*ial 5 java events javafx intellij-idea

我正在尝试使用 JavaFX 打开多个窗口,我有一个事件侦听器,可以在单击按钮时打开一个新窗口,如下所示:

@FXML
private void joinAction() {
    Parent root;
    try {
        Stage stage = (Stage) joinButton.getScene().getWindow();
        stage.close();

        root = FXMLLoader.load(getClass().getResource("main.fxml"));
        stage = new Stage();
        stage.setTitle("TuneUs");
        stage.setScene(new Scene(root));
        stage.show();

    } catch (IOException e) {e.printStackTrace();}
}
Run Code Online (Sandbox Code Playgroud)

第一个窗口打开,新窗口打开,但我的问题是让事件与我的第二个窗口一起工作

main.fxml我有这一行:

<TextField id="chat_bar" onAction="#sendChat" layoutX="14.0" layoutY="106.0" prefHeight="22.0" prefWidth="403.0"/>
Run Code Online (Sandbox Code Playgroud)

然后在我的控制器类中我有这个方法:

@FXML
private void sendChat() {
    System.out.println("test");
}
Run Code Online (Sandbox Code Playgroud)

但 Intellij 告诉我;没有为顶级元素指定控制器

所以,我的问题是:我是否需要创建多个控制器类,或者我可以为多个窗口只使用一个类吗?

Jam*_*s_D 3

推荐的方法是为每个 FXML 定义一个控制器。由于控制器非常轻量级,因此不会增加太多开销。main.fxml 文件的控制器可能很简单

import javafx.fxml.FXML ;

public class MainController {
  @FXML
  private void sendChat() {
    // ...
  }
}
Run Code Online (Sandbox Code Playgroud)

我已在单个项目中使用这种方法处理相当大量的 FXML 文件和相应的控制器,并且在管理代码等方面没有遇到任何问题。我建议使用以下形式的命名约定Main.fxml <-> MainController

如果您的控制器需要共享数据,请使用传递参数 JavaFX FXML中概述的技术

正如 @Vertex 在评论中指出的那样,该方法提供了另一种方法FXMLLoader.setController(...)。所以在上面的例子中,你可以这样做

@FXML
private void joinAction() {
    Parent root;
    try {
        Stage stage = (Stage) joinButton.getScene().getWindow();
        stage.close();

        FXMLLoader loader = new FXMLLoader (getClass().getResource("main.fxml"));
        loader.setController(this);
        root = loader.load();
        stage = new Stage();
        stage.setTitle("TuneUs");
        stage.setScene(new Scene(root));
        stage.show();

    } catch (IOException e) {e.printStackTrace();}
}

@FXML
private void sendChat() {
    // ...
}
Run Code Online (Sandbox Code Playgroud)

fx:id如果您不通过 FXML 注入设置任何字段(控件)(即使用fxml 中的属性和@FXML控制器中的相应注释),则此方法很好。如果是的话,将很难跟踪这些字段的设置时间。此外,如果您的joinAction处理程序被多次调用,您将拥有由 main.fxml 创建的节点的多个实例,但所有实例都共享一个控制器实例(并因此覆盖相同的注入字段)。另请注意,使用这种方法,您的方法将加载原始 fxml 文件加载 main.fxml 文件时initialize()被调用,这几乎肯定会导致不良效果。

最后一点:如果您有许多 FXML 文件和相应的控制器,您可能需要查看afterburner.fx 框架。这是一个非常轻量级的框架,它强制要求 FXML 文件及其相应控制器的命名约定,并且还提供了一种(非常)简单的机制来在它们之间共享数据。