2012-05-25 10 views
41

Chciałbym komunikować się z klasą kontrolera FXML w dowolnym momencie, aby zaktualizować informacje na ekranie z głównej aplikacji lub innych etapów.Dostęp do kontrolera FXML klasa

Czy to możliwe? Nie znalazłem żadnego sposobu, żeby to zrobić.

Funkcje statyczne mogą być sposobem, ale nie mają dostępu do formantów formularza.

Wszelkie pomysły?

Odpowiedz

69

Można dostać regulator z FXMLLoader

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

przechowywać go w swojej głównej scenie i zapewniają getFooController() metoda getter.
z innych klas lub etapach, za każdym razem, gdy trzeba odświeżyć stronę załadowany „foo.fxml”, zapytaj go z kontrolerem:

getFooController().updatePage(strData); 

updatePage() może być coś takiego:

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

w klasie FooController.
W ten sposób inni użytkownicy stron nie przejmują się wewnętrzną strukturą strony, np. Co i gdzie jest Label lblData.

Zobacz także https://stackoverflow.com/a/10718683/682495. W JavaFX 2.2 FXMLLoader została ulepszona.

+2

i odkryli, że przy użyciu funkcji statycznych jest łatwiejsze i działa lepiej niż tego rozwiązania (w najmniej dla mnie). Kluczem do uzyskania dostępu do elementów sterujących jest posiadanie publicznej statycznej instancji klasy, która ma dostęp do wszystkich elementów sterujących i metod publicznych. – betaman

+0

Wiem, że to stare pytanie ... ale czy ktoś może podać więcej szczegółów na temat odpowiedzi w.r.t. gdzie znajdują się pierwsze 3 linie kodu i gdzie znajduje się getFooController()? – adeena

+0

@adeena, FooController jest klasą kontrolera zdefiniowaną przez ciebie w "foo.fxml", aw kodzie nie ma getFooController(). –

2

Przy ładowaniu obiektu z ekranu głównego, jednym ze sposobów przekazywania danych, które znalazłem i działa, jest użycie odnośnika, a następnie ustawienie danych w niewidocznej etykiecie, którą będę mógł pobrać później z klasy kontrolera. Tak:

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

To działa, ale nie musi być lepszy sposób.

7

Innym rozwiązaniem jest ustawienie kontrolera z poziomu kontrolera, tak jak ...

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

} 

To rozwiązanie wolę używać, ponieważ kod jest nieco niechlujny, aby stworzyć w pełni funkcjonalną instancję FXMLLoader które prawidłowo obsługuje lokalnych zasobów itp

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

kontra

@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

To rozwiązanie działa również w poprzednich wersjach JavaFX (<2.2). – Neil

7

Aby pomóc w wyjaśnieniu zaakceptowanej odpowiedzi, a może zaoszczędzić trochę czasu innym osobom, które są nowicjuszami w JavaFX:

dla aplikacji JavaFX FXML, NetBeans będzie automatycznie wygenerować metodę startu w głównej klasie następująco:

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

Teraz, wszystko co trzeba zrobić, aby mieć dostęp do klasy kontrolera, aby zmienić FXMLLoader load() metodą od statycznej realizacji do instancja realizacji i wtedy możemy użyć metody instancji, aby uzyskać sterownik w następujący sposób:

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

bardzo ładna odpowiedź z wyraźnymi komentarzami! – user2407334

Powiązane problemy