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

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

问题描述

我有以下代码:

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

}



我试图使用WebEngine和ToggleButton来自MainController中控制器的对象(我在MainController中生成了getters和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

推荐答案

您正手动创建控制器实例

You are creating a controller instance "by hand" with

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

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(...)的调用,这避免了 ConnectionErrorController MainController 。但是,由于您似乎是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或其他Controller的对象在正确的Controller类中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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