javafx 在正确的控制器类中使用来自 MainController 或其他控制器的对象 [英] javafx using objects from MainController or other Controllers in proper Controller class

查看:25
本文介绍了javafx 在正确的控制器类中使用来自 MainController 或其他控制器的对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码:

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 中控制器的 WebEngine 和 ToggleButton 对象(我在 MainController 中为它们生成了 getter 和 setter):

I am trying to use WebEngine and ToggleButton Objects from controllers in MainController (I generated getters and setters to them in MainController):

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 中的控制器时.如何从 ConnectionErrorController 中的控制器正确引用 ToggleButton i WebEngine 对象?问候

But its still returns NullPointerException. I had same problem, when I tried simply make references to the controllers in ConnectionErrorController. How to refer to the ToggleButton i WebEngine Objects from controllers in ConnectionErrorController properly? Regards

推荐答案

您正在使用

MainController mc = new MainController();

@FXML 注释的字段由 FXMLLoader 在为您创建控制器时初始化,作为加载 FXML 文件的过程的一部分.由于您创建的控制器不是由 FXMLLoader 创建的控制器实例,它的 @FXML 注释字段未初始化(即它们为空),因此您得到一个空值指针异常.

@FXML-annotated fields are initialized by the FXMLLoader when it creates the controller for you as part of the process of loading the FXML file. Since the controller you created is not the controller instance created by the FXMLLoader, its @FXML-annotated fields are uninitialized (i.e. they are null), and hence you get a null pointer exception.

您可以在调用 后,通过在 FXMLLoader 实例上调用 getController() 来获取对 FXMLLoader 创建的控制器的引用load().

You can get a reference to the controller created by the FXMLLoader by calling getController() on the FXMLLoader instance after calling load().

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

If you want one controller to communicate with another, then pass the reference to one controller to the other controller, by defining appropriate methods in the second 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 文件,那么您可以执行以下操作:

Assuming you are loading the second fxml file in a method in MainController, you can then just do something like:

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 新手,这种更简单的方法可能更合适.

Note that there are much more elegant ways of solving this problem, such as passing the ConnectionErrorController a callback function (in the form of a lambda expression) to process the call to play(...), which avoid the tight coupling between the ConnectionErrorController and the MainController. However, as you seem to be new to Java, this simpler approach might be more suitable.

有关将值传递给控制器​​的更多信息,请参阅传递参数 JavaFX FXML.

See Passing Parameters JavaFX FXML for more information on passing values to controllers.

这篇关于javafx 在正确的控制器类中使用来自 MainController 或其他控制器的对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆