2012-05-25 12 views
41

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

¿Esto es posible? No he encontrado ninguna forma de hacerlo.

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

¿Alguna idea?

Respuesta

69

, usted puede obtener el controlador de la tienda de FXMLLoader

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

en su escenario principal y proporcionar getFooController método getter().
de otras clases o etapas, cada vez que se necesita refrescar la página cargada "foo.fxml", pregunta 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 está Label lblData.

También vea el https://stackoverflow.com/a/10718683/682495. En JavaFX 2.2 se mejora el FXMLLoader.

+2

he encontrado que el uso de funciones estáticas es más fácil y funciona mejor que esta solución (al menos para mí). La clave para poder acceder a los controles es tener una instancia pública estática de la clase que tiene acceso a todos los controles y métodos públicos. – betaman

+0

Sé que esta es una vieja pregunta ... pero ¿alguien puede proporcionar más detalles sobre la respuesta w.r.t. donde van las primeras 3 líneas de código y donde va el getFooController()? – adeena

+0

@adeena, FooController es una clase de controlador definida por usted en "foo.fxml", y no hay getFooController() en el código. –

2

En la carga del objeto desde la pantalla principal, una forma de pasar datos que he encontrado y funciona es usar la búsqueda y luego establecer los datos dentro de una etiqueta invisible que puedo recuperar más tarde desde la clase del controlador. De esta manera:

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.

7

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

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 yo prefiero usar ya que el código es un poco desordenado para crear una instancia de FXMLLoader completamente funcional que maneja adecuadamente los recursos locales, etc.

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

frente

@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)); 
} 
+0

Esta solución también funciona para versiones anteriores de JavaFX (<2.2). – Neil

7

Solo para ayudar a aclarar la respuesta aceptada y quizás ahorrar algo de tiempo para otras que son nuevas en JavaFX:

para una aplicación JavaFX FXML, NetBeans generará automáticamente el método de inicio de 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 del controlador es cambiar el FXMLLoader load() método de la aplicación estática a una implementación instancia y luego podemos utilizar 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(); 
} 
+0

muy buena respuesta con comentarios claros! – user2407334

Cuestiones relacionadas