tutorial - pasar datos entre controladores javafx
javafx utilizando objetos de MainController u otros controladores en la clase de controlador adecuada (1)
Está creando una instancia de controlador "a mano" con
MainController mc = new MainController();
@FXML
FXML: los campos anotados son inicializados por FXMLLoader
cuando crea el controlador para usted como parte del proceso de carga del archivo FXML. Dado que el controlador que ha creado no es la instancia del controlador creada por el FXMLLoader
, sus campos @FXML
-annotated no están inicializados (es decir, son nulos) y, por lo tanto, obtiene una excepción de puntero nulo.
Puede obtener una referencia al controlador creado por FXMLLoader
llamando a getController()
en la instancia de FXMLLoader
después de llamar a load()
.
Si desea que un controlador se comunique con otro, pase la referencia a un controlador al otro controlador, definiendo los métodos apropiados en el segundo controlador:
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();
}
});
// ...
}
}
Suponiendo que está cargando el segundo archivo fxml en un método en MainController
, puede hacer algo como:
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...
}
// ...
}
Tenga en cuenta que hay formas mucho más elegantes de resolver este problema, como pasar el ConnectionErrorController
una función de devolución de llamada (en forma de una expresión lambda) para procesar la llamada a play(...)
, lo que evita el estrecho acoplamiento entre ConnectionErrorController
y el MainController
. Sin embargo, como pareces ser nuevo en Java, este enfoque más simple podría ser más adecuado.
Consulte Pasar parámetros JavaFX FXML para obtener más información sobre cómo pasar valores a los controladores.
Tengo el siguiente código:
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();
}
});
}
}
Estoy tratando de usar WebEngine y ToggleButton Objects desde los controladores en MainController (les generé getters y setters en 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;
}
Pero aún así devuelve NullPointerException. Tuve el mismo problema, cuando intenté simplemente hacer referencias a los controladores en ConnectionErrorController. ¿Cómo hacer referencia a los objetos ToggleButton i WebEngine de los controladores en ConnectionErrorController correctamente? Saludos