2012-05-25 1 views
41

Desidero comunicare con una classe di controller FXML in qualsiasi momento per aggiornare le informazioni sullo schermo dall'applicazione principale o da altre fasi.Accesso alla classe controller FXML

È possibile? Non ho trovato alcun modo per farlo.

Le funzioni statiche potrebbero essere un modo, ma non hanno accesso ai controlli del modulo.

Qualche idea?

risposta

69

si può ottenere il controller dal FXMLLoader

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

negozio nel vostro palco principale e di fornire getFooController) metodo getter (.
Da altre classi o stadi, ogni volta in cui è necessario aggiornare la pagina "foo.fxml" caricato, chiedere dal suo controllore:

getFooController().updatePage(strData); 

updatePage() può essere qualcosa del tipo:

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

nella classe FooController.
In questo modo, gli altri utenti della pagina non si preoccupano della struttura interna della pagina come cosa e dove sia Label lblData.

Vedere anche https://stackoverflow.com/a/10718683/682495. In JavaFX 2.2 FXMLLoader è stato migliorato.

+2

ho trovato che l'uso di funzioni statiche è più facile e funziona meglio di questa soluzione (in almeno per me). La chiave per poter accedere ai controlli è avere un'istanza statica pubblica della classe che abbia accesso a tutti i controlli e ai metodi pubblici. – betaman

+0

So che questa è una vecchia domanda ... ma chiunque può fornire maggiori dettagli sulla risposta w.r.t. dove vanno le prime 3 righe di codice e dove va getFooController()? – adeena

+0

@adeena, FooController è una classe controller definita dall'utente in "foo.fxml" e nel codice non è presente getFooController(). –

2

Sul caricamento dell'oggetto dalla schermata principale, un modo per passare i dati che ho trovato e funziona è utilizzare la ricerca e quindi impostare i dati all'interno di un'etichetta invisibile che posso recuperare in seguito dalla classe controller. Mi piace:

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

Questo funziona, ma ci deve essere un modo migliore.

7

Un'altra soluzione è quella di impostare il controller dalla classe controller, in questo modo ...

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

} 

Questa è la soluzione che preferisco usare dato che il codice è un po 'disordinato per creare un'istanza FXMLLoader completamente funzionale che gestisce correttamente le risorse locali, ecc

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

contro

@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

Questa soluzione funziona anche per le versioni precedenti di JavaFX (<2.2). – Neil

7

Solo per aiutare a chiarire la risposta accettata e magari risparmiare un po 'di tempo per gli altri che sono nuovi a JavaFX:

per un'applicazione JavaFX FXML, NetBeans sarà generare automaticamente il metodo di partenza nella classe principale come segue:

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

Ora, tutto quello che dobbiamo fare per avere accesso alla classe di controllo è quello di cambiare la FXMLLoader load() metodo dall'implementazione statica a un'implementazione istanziati e quindi siamo in grado di utilizzare il metodo dell'istanza per ottenere il controller, in questo modo:

//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

risposta molto bella con commenti chiari! – user2407334

Problemi correlati