javafx 在适当的 Controller 类中使用 MainController 或其他 Controller 中的对象

标签 java javafx controller fxml

我有以下代码:

package pl.javastart.youtufy.controller;

import java.net.URL;
import java.util.ResourceBundle;

import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ToggleButton;
import javafx.scene.web.WebEngine;
import javafx.stage.Stage;

public class ConnectionErrorController implements Initializable {

    @FXML
    private Label infoLabel;

    @FXML
    private Button tryButton;

    @FXML
    private Button exitButton;


    @Override
    public void initialize(URL location, ResourceBundle resources) {

        MainController mc = new MainController();

        infoLabel.setText("Connection lost, please try again");
        tryButton.setText("try again");
        exitButton.setText("exit");

        tryButton.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {

                WebEngine webEngine = mc.getContentPaneController().getVideoWebView().getEngine(); // 1
                ToggleButton playButton = mc.getControlPaneController().getPlayButton(); // 2
                Node source = (Node) event.getSource();
                Stage stage = (Stage) source.getScene().getWindow();
                if (mc.testInet()) {
                    stage.close();
                    mc.play(webEngine, playButton);
                } else {
                    stage.close();
                    MainController.exist = false;
                }
            }
        });

        exitButton.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                Platform.exit();
            }
        });
    }

}

我正在尝试使用 MainController 中 Controller 中的 WebEngine 和 ToggleButton 对象(我在 MainController 中为它们生成了 getter 和 setter):

public class MainController implements Initializable {

@FXML
private ContentPaneController contentPaneController;

@FXML
private ControlPaneController controlPaneController;

@FXML
private MenuPaneController menuPaneController;

@FXML
private SearchPaneController searchPaneController;

private Youtube youtubeInstance;

public static boolean exist = false;

public ControlPaneController getControlPaneController() {
    return controlPaneController;
}

public void setControlPaneController(ControlPaneController controlPaneController) {
    this.controlPaneController = controlPaneController;
}

public ContentPaneController getContentPaneController() {
    return contentPaneController;
}

public void setContentPaneController(ContentPaneController contentPaneController) {
    this.contentPaneController = contentPaneController;
}

但它仍然返回 NullPointerException。当我尝试简单地引用 ConnectionErrorController 中的 Controller 时,我遇到了同样的问题。如何正确从 ConnectionErrorController 中的 Controller 引用 ToggleButton i WebEngine 对象? 问候

最佳答案

您正在“手动”创建一个 Controller 实例

MainController mc = new MainController();

@FXML 带注释的字段由 FXMLLoader 在加载 FXML 文件过程中为您创建 Controller 时初始化。由于您创建的 Controller 不是由 FXMLLoader 创建的 Controller 实例,因此它的 @FXML 注释字段未初始化(即它们为 null),因此您会得到 null指针异常。

您可以在调用 后,通过在 FXMLLoader 实例上调用 getController() 来获取对 FXMLLoader 创建的 Controller 的引用加载()

如果您希望一个 Controller 与另一个 Controller 通信,请通过在第二个 Controller 中定义适当的方法,将对一个 Controller 的引用传递给另一个 Controller :

public class ConnectionErrorController implements Initializable {

    private MainController mainController ;

    public void setMainController(MainController mainController) {
        this.mainController = mainController ;
    }

    // ...

    @Override
    public void initialize(URL location, ResourceBundle resources) {

        infoLabel.setText("Connection lost, please try again");
        tryButton.setText("try again");
        exitButton.setText("exit");

        tryButton.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {

                WebEngine webEngine = mainController.getContentPaneController().getVideoWebView().getEngine(); // 1
                ToggleButton playButton = mainController.getControlPaneController().getPlayButton(); // 2
                if (mainController.testInet()) {
                    mainController.play(webEngine, playButton);
                } else {
                    // obviously you can now do something better than the "public static field hack" here:
                    MainController.exist = false;
                }
                tryButton.getScene().getWindow().hide();
            }
        });

        // ...
    }
}    

假设您正在 MainController 中的方法中加载第二个 fxml 文件,那么您可以执行以下操作:

public class MainController {

    // ...

    public void showConnectionErrorWindow(String fileName) {

        FXMLLoader loader = new FXMLLoader(getClass().getResource("path/to/ConnectionError.fxml"));
        Parent root = loader.load();
        ConnectionErrorController connectionErrorController = loader.getController();
        connectionErrorController.setMainController(this);

        Scene scene = new Scene(root);
        Stage stage = new Stage();
        // etc...
    }

    // ...
}

请注意,有很多更优雅的方法可以解决此问题,例如向 ConnectionErrorController 传递一个回调函数(以 lambda 表达式的形式)来处理对 play( ...),这避免了 ConnectionErrorControllerMainController 之间的紧密耦合。但是,由于您似乎是 Java 新手,这种更简单的方法可能更合适。

参见Passing Parameters JavaFX FXML有关将值传递给 Controller ​​的更多信息。

关于javafx 在适当的 Controller 类中使用 MainController 或其他 Controller 中的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43710971/

相关文章:

java - 线程对象的run方法

java - Selenium - Webdriver 可执行文件不存在错误

java - Objective-C 方法重载

javafx,拖动优化 - 各种想法

asp.net-mvc - 无法检索 'MyService.Entities.Email' 的元数据。 'System.Data.Entity.Internal.AppConfig' 的类型初始值设定项引发异常

Java:在 main 方法中使用 System.exit() 和 (String [] args) 的用途

java - 如何编辑不同类中主类中标签的颜色?

java - 无法在另一个包中加载 FXML (JavaFX)

ios - 查看 Controller 层次结构和设备方向变化

laravel - 将页面 URL 参数传递给 Laravel 5.2 中的 Controller