Accediendo a la clase de controlador FXML

Resuelto betaman asked hace 12 años • 4 respuestas

Me gustaría comunicarme con una clase de controlador FXML en cualquier momento, para actualizar información en pantalla desde la aplicación principal u otras etapas.

es posible? No he encontrado ninguna manera de hacerlo.

Las funciones estáticas podrían ser una forma, pero no tienen acceso a los controles del formulario.

¿Algunas ideas?

betaman avatar May 25 '12 15:05 betaman
Aceptado

Puede obtener el controlador enFXMLLoader

FXMLLoader fxmlLoader = new FXMLLoader();
Pane p = fxmlLoader.load(getClass().getResource("foo.fxml").openStream());
FooController fooController = (FooController) fxmlLoader.getController();

guárdelo en su escenario principal y proporcione el método getter getFooController().
Desde otras clases o etapas, cada vez que necesites actualizar la página "foo.fxml" cargada, solicítalo desde su controlador:

getFooController().updatePage(strData);

updatePage() puede ser algo como:

// ...
@FXML private Label lblData;
// ...
public void updatePage(String data){
    lblData.setText(data);
}
// ...

en la clase FooController.
De esta manera, otros usuarios de la página no se preocupan por la estructura interna de la página, como qué y dónde Label lblDataestá.

Mire también https://stackoverflow.com/a/10718683/682495 . En JavaFX 2.2 FXMLLoaderestá mejorado.

Uluk Biy avatar May 25 '2012 11:05 Uluk Biy

Solo para ayudar a aclarar la respuesta aceptada y tal vez ahorrar un poco de tiempo a otras personas que son nuevas en JavaFX:

Para una aplicación JavaFX FXML, NetBeans generará automáticamente su método de inicio en la clase principal de la siguiente manera:

@Override
public void start(Stage stage) throws Exception {
    Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));

    Scene scene = new Scene(root);

    stage.setScene(scene);
    stage.show();
}

Ahora, todo lo que necesitamos hacer para tener acceso a la clase de controlador es cambiar el load()método FXMLLoader de la implementación estática a una implementación instanciada y luego podemos usar el método de la instancia para obtener el controlador, así:

//Static global variable for the controller (where MyController is the name of your controller class
static MyController myControllerHandle;

@Override
public void start(Stage stage) throws Exception {
    //Set up instance instead of using static load() method
    FXMLLoader loader = new FXMLLoader(getClass().getResource("FXMLDocument.fxml"));
    Parent root = loader.load();

    //Now we have access to getController() through the instance... don't forget the type cast
    myControllerHandle = (MyController)loader.getController();

    Scene scene = new Scene(root);

    stage.setScene(scene);
    stage.show();
}
DatuPuti avatar Feb 06 '2017 16:02 DatuPuti

Otra solución es configurar el controlador desde su clase de controlador, así...

public class Controller implements javafx.fxml.Initializable {

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        // Implementing the Initializable interface means that this method
        // will be called when the controller instance is created
        App.setController(this);
    }

}

Esta es la solución que prefiero usar ya que el código es algo complicado para crear una instancia de FXMLLoader completamente funcional que maneje adecuadamente los recursos locales, etc.

@Override
public void start(Stage stage) throws Exception {
    Parent root = FXMLLoader.load(getClass().getResource("/sample.fxml"));
}

versus

@Override
public void start(Stage stage) throws Exception {
    URL location = getClass().getResource("/sample.fxml");
    FXMLLoader loader = createFXMLLoader(location);
    Parent root = loader.load(location.openStream());
}

public FXMLLoader createFXMLLoader(URL location) {
    return new FXMLLoader(location, null, new JavaFXBuilderFactory(), null, Charset.forName(FXMLLoader.DEFAULT_CHARSET_NAME));
}
Caleb avatar Jul 18 '2015 15:07 Caleb

Al cargar el objeto desde la pantalla principal, una forma de pasar datos que encontré y que funciona es usar la búsqueda y luego configurar los datos dentro de una etiqueta invisible que puedo recuperar más tarde desde la clase del controlador. Como esto:

Parent root = FXMLLoader.load(me.getClass().getResource("Form.fxml"));
Label lblData = (Label) root.lookup("#lblData");
if (lblData!=null) lblData.setText(strData); 

Esto funciona, pero debe haber una manera mejor.

betaman avatar May 25 '2012 08:05 betaman