JavaFX: jak uzyskać stage z kontrolera podczas inicjalizacji?
Chcę obsługiwać zdarzenia sceniczne (tj. ukrywanie) z mojej klasy kontrolerów. Więc wszystko, co muszę zrobić, to dodać słuchacza przez
((Stage)myPane.getScene().getWindow()).setOn*whatIwant*(...);
Ale problem polega na tym, że inicjalizacja rozpoczyna się zaraz po
Parent root = FXMLLoader.load(getClass().getResource("MyGui.fxml"));
I przed
Scene scene = new Scene(root);
stage.setScene(scene);
Tak więc .getScene () zwraca null.
Jedynym obejściem, jakie znalazłem, jest dodanie słuchacza do myPane.sceneProperty (), a gdy staje się nie null dostaję scene, dodaję do niego .windowProperty () my !cholera! obsługa słuchacza który w końcu odzyskałem. A wszystko to kończy się na ustawieniu pożądanych słuchaczy do wydarzeń scenicznych. Myślę, że jest zbyt wielu słuchaczy. Czy to jedyny sposób na rozwiązanie mojego problemu?
7 answers
Możesz pobrać instancję kontrolera z FXMLLoader
po inicjalizacji przez getController()
, ale musisz utworzyć instancję FXMLLoader
zamiast używać metod statycznych.
Przeszedłbym etap po wywołaniu load()
bezpośrednio do kontrolera później:
FXMLLoader loader = new FXMLLoader(getClass().getResource("MyGui.fxml"));
Parent root = (Parent)loader.load();
MyController controller = (MyController)loader.getController();
controller.setStageAndSetupListeners(stage); // or what you want to do
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-02-11 16:09:31
Wystarczy, że podasz AnchorPane
Identyfikator, a potem dostaniesz Stage
z tego.
@FXML private AnchorPane ap;
Stage stage = (Stage) ap.getScene().getWindow();
Stąd możesz dodać Listener
, które potrzebujesz.
Edit: zgodnie z poniższym opisem EarthMind, nie musi to być element AnchorPane
; może to być dowolny element, który zdefiniowałeś.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-18 21:01:39
Wiem, że to nie jest odpowiedź, ale IMO proponowane rozwiązania nie są dobre(a twój własny sposób jest). Dlaczego? Ponieważ zależą one od stanu aplikacji. W JavaFX sterowanie, scena i scena nie zależą od siebie nawzajem. Oznacza to, że kontrola może żyć bez dodawania do sceny, a scena może istnieć bez dołączania do sceny. Następnie, w momencie instant T1, kontrola może zostać dołączona do sceny, a w momencie instant t2, scena może zostać dodana do sceny (i to wyjaśnia, dlaczego są obserwowalnymi własnościami siebie nawzajem).
Więc podejście, które sugeruje uzyskanie referencji kontrolera i wywołanie metody, przejście do niej etapu dodaje stan do aplikacji. Oznacza to, że musisz wywołać tę metodę w odpowiednim momencie, tuż po utworzeniu etapu. Innymi słowy, musisz wykonać zamówienie teraz: 1-Utwórz scenę 2-przekazać ten utworzony etap do kontrolera za pomocą metody.
Nie możesz (lub nie powinieneś) zmienić tej kolejności w tym podejdźcie. Więc straciłeś bezpaństwowość. A w oprogramowaniu, ogólnie, państwo jest złem. Idealnie, metody nie powinny wymagać żadnego zamówienia wywołania.
Więc jakie jest właściwe rozwiązanie? Istnieją dwie alternatywy:
1 - twoje podejście, we właściwościach nasłuchu kontrolera, aby uzyskać scenę. Myślę, że to właściwe podejście. Tak:
pane.sceneProperty().addListener((observableScene, oldScene, newScene) -> {
if (oldScene == null && newScene != null) {
// scene is set for the first time. Now its the time to listen stage changes.
newScene.windowProperty().addListener((observableWindow, oldWindow, newWindow) -> {
if (oldWindow == null && newWindow != null) {
// stage is set. now is the right time to do whatever we need to the stage in the controller.
((Stage) newWindow).maximizedProperty().addListener((a, b, c) -> {
if (c) {
System.out.println("I am maximized!");
}
});
}
});
}
});
2-robisz to, co musisz zrobić, gdzie tworzysz Stage
(a nie tego chcesz):
Stage stage = new Stage();
stage.maximizedProperty().addListener((a, b, c) -> {
if (c) {
System.out.println("I am maximized!");
}
});
stage.setScene(someScene);
...
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-01 17:58:35
Najprostszym sposobem uzyskania obiektu stage w kontrolerze jest:
-
Dodaj dodatkową metodę w stworzonej przez siebie klasie kontrolera like (będzie to metoda setter do ustawiania stage w klasie kontrolera),
private Stage myStage; public void setStage(Stage stage) { myStage = stage; }
-
Get controller in start method and set stage
FXMLLoader loader = new FXMLLoader(getClass().getResource("MyFXML.fxml")); OwnController controller = loader.getController(); controller.setStage(this.stage);
-
Teraz możesz uzyskać dostęp do sceny w controller
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-15 04:17:31
Przypisz FX:id lub zadeklaruj zmienną do/dowolnego węzła: anchorpane, button, itd. Następnie dodaj do niego funkcję obsługi zdarzeń i wprowadź podany poniżej kod:
Stage stage = (Stage)((Node)((EventObject) eventVariable).getSource()).getScene().getWindow();
Hope, to działa dla Ciebie!!Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-11 10:13:57
Platforma.runLater działa, aby zapobiec wykonaniu do momentu zakończenia inicjalizacji. W tym przypadku chcę odświeżyć widok listy za każdym razem, gdy zmieniam rozmiar okna.
Platform.runLater(() -> {
((Stage) listView.getScene().getWindow()).widthProperty().addListener((obs, oldVal, newVal) -> {
listView.refresh();
});
});
W Twoim przypadku
Platform.runLater(()->{
((Stage)myPane.getScene().getWindow()).setOn*whatIwant*(...);
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-01-23 14:31:58
Można uzyskać za pomocą node.getScene
, jeśli nie wywoła się z Platform.runLater
, wynikiem jest wartość null.
Przykładowa wartość null:
node.getScene();
Przykład brak wartości null:
Platform.runLater(() -> {
node.getScene().addEventFilter(KeyEvent.KEY_PRESSED, event -> {
//your event
});
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-02 06:13:52