javafx 在适当的控制器中使用来自 MainController 或其他控制器的对象 class
javafx using objects from MainController or other Controllers in proper Controller class
我有以下代码:
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):
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;
}
但它仍然是 returns NullPointerException。我遇到了同样的问题,当我尝试简单地引用 ConnectionErrorController 中的控制器时。如何从 ConnectionErrorController 中的控制器正确引用 ToggleButton i WebEngine 对象?
此致
您正在创建控制器实例 "by hand"
MainController mc = new MainController();
@FXML
-注释字段由 FXMLLoader
在它为您创建控制器时作为加载 FXML 文件过程的一部分进行初始化。由于您创建的控制器不是由 FXMLLoader
创建的控制器实例,其 @FXML
-注释字段未初始化(即它们为空),因此您得到一个空指针异常。
您可以在调用 load()
.
之后调用 FXMLLoader
实例上的 getController()
来获取对 FXMLLoader
创建的控制器的引用
如果您希望一个控制器与另一个控制器通信,则通过在第二个控制器中定义适当的方法,将对一个控制器的引用传递给另一个控制器:
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(...)
的调用,这避免了 ConnectionErrorController
和 MainController
之间的紧耦合。但是,由于您似乎是 Java 的新手,所以这种更简单的方法可能更合适。
有关将值传递给控制器的详细信息,请参阅 Passing Parameters JavaFX 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 中使用来自控制器的 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;
}
但它仍然是 returns NullPointerException。我遇到了同样的问题,当我尝试简单地引用 ConnectionErrorController 中的控制器时。如何从 ConnectionErrorController 中的控制器正确引用 ToggleButton i WebEngine 对象? 此致
您正在创建控制器实例 "by hand"
MainController mc = new MainController();
@FXML
-注释字段由 FXMLLoader
在它为您创建控制器时作为加载 FXML 文件过程的一部分进行初始化。由于您创建的控制器不是由 FXMLLoader
创建的控制器实例,其 @FXML
-注释字段未初始化(即它们为空),因此您得到一个空指针异常。
您可以在调用 load()
.
FXMLLoader
实例上的 getController()
来获取对 FXMLLoader
创建的控制器的引用
如果您希望一个控制器与另一个控制器通信,则通过在第二个控制器中定义适当的方法,将对一个控制器的引用传递给另一个控制器:
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(...)
的调用,这避免了 ConnectionErrorController
和 MainController
之间的紧耦合。但是,由于您似乎是 Java 的新手,所以这种更简单的方法可能更合适。
有关将值传递给控制器的详细信息,请参阅 Passing Parameters JavaFX FXML。