Я хочу обрабатывать сценические события (т.е. скрытие) из моего класса контроллера. Итак, все, что мне нужно сделать, это добавить слушателя через
((Stage)myPane.getScene().getWindow()).setOn*whatIwant*(...);
но проблема в том, что инициализация начинается сразу после
Parent root = FXMLLoader.load(getClass().getResource("MyGui.fxml"));
и раньше
Scene scene = new Scene(root);
stage.setScene(scene);
таким образом .getScene () возвращает null.
Единственный обходной путь, который я нашел сам, - это добавить слушателя к myPane.sceneProperty (), и когда он станет не нулевым, я получаю сцену, добавляю к нему .windowProperty () my! Черт возьми! Обработка слушателя, которую я, наконец, извлекаю stage. И все это заканчивается настройкой желаемых слушателей для сценических событий. Я считаю, что слушателей слишком много. Это единственный способ решить мою проблему?
load()
методу. (Кроме того, javadoc ongetController
звучит так, как будто он должен бытьsetController
Все, что вам нужно, это дать
AnchorPane
идентификатор, и тогда вы сможете получитьStage
от него.@FXML private AnchorPane ap; Stage stage = (Stage) ap.getScene().getWindow();
Отсюда вы можете добавить то,
Listener
что вам нужно.Изменить: как указано ниже EarthMind, это не обязательно должен быть
AnchorPane
элемент; это может быть любой элемент, который вы определили.источник
element
может быть любой элемент сfx:id
в этом окне:Stage stage = (Stage) element.getScene().getWindow();
. Например, если в ваших окнах есть только значокButton
сfx:id
символом, используйте его, чтобы получить сцену.getScene()
все еще возвращаетсяnull
.bgimage.sceneProperty().addListener((observableScene, oldScene, newScene) -> { if (oldScene == null && newScene != null) { bgimage.fitWidthProperty().bind(newScene.widthProperty()); ... } });
Я знаю, что это не тот ответ, который вам нужен, но предлагаемые решения IMO не очень хороши (и ваш собственный путь). Зачем? Потому что они зависят от состояния приложения. В JavaFX элемент управления, сцена и этап не зависят друг от друга. Это означает, что элемент управления может существовать без добавления к сцене, а сцена может существовать без привязки к сцене. Затем в момент времени t1 элемент управления может быть прикреплен к сцене, а в момент t2 эта сцена может быть добавлена к сцене (и это объясняет, почему они являются наблюдаемыми свойствами друг друга).
Таким образом, подход, который предлагает получить ссылку на контроллер и вызвать метод, передав ему этап, добавляет состояние в ваше приложение. Это означает, что вам нужно вызвать этот метод в нужный момент, сразу после создания этапа. Другими словами, вам нужно выполнить порядок сейчас: 1- Создать этап 2- Передать этот созданный этап контроллеру с помощью метода.
Вы не можете (или не должны) изменять этот порядок при таком подходе. Итак, вы потеряли безгражданство. А в софте вообще состояние зло. В идеале методы не должны требовать какого-либо порядка вызова.
Так какое же правильное решение? Есть две альтернативы:
1- Ваш подход в свойствах прослушивания контроллера, чтобы получить сцену. Я считаю, что это правильный подход. Как это:
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- Вы делаете то, что вам нужно, там, где вы создаете
Stage
(а это не то, что вы хотите):Stage stage = new Stage(); stage.maximizedProperty().addListener((a, b, c) -> { if (c) { System.out.println("I am maximized!"); } }); stage.setScene(someScene); ...
источник
pane
к сцене, которая уже прикреплена к сцене, это не сработает, верно? Разве не следует проверятьsceneProperty
слушателя и добавлятьstageProperty
слушателя только в том случае, если этап все еще нулевой? А иначе сразу делать то, что мне нужно?Самый простой способ получить объект сцены в контроллере:
Добавьте дополнительный метод в собственный созданный класс контроллера, например (это будет метод установки для установки сцены в классе контроллера),
private Stage myStage; public void setStage(Stage stage) { myStage = stage; }
Получить контроллер в методе запуска и настроить этап
FXMLLoader loader = new FXMLLoader(getClass().getResource("MyFXML.fxml")); OwnController controller = loader.getController(); controller.setStage(this.stage);
Теперь вы можете получить доступ к сцене в контроллере
источник
stage
это.Назначьте fx: id или объявите переменную для / любого узла: anchorpane, button и т. Д. Затем добавьте к нему обработчик событий и внутри этого обработчика событий вставьте указанный ниже код:
Надеюсь, что это работает для вас!!
источник
Platform.runLater предотвращает выполнение до завершения инициализации. В этом случае я хочу обновлять представление списка каждый раз, когда меняю размер окна.
в твоем случае
источник
Вы можете получить
node.getScene
, если вы не звоните изPlatform.runLater
, результатом будет нулевое значение.пример нулевого значения:
пример без нулевого значения:
Platform.runLater(() -> { node.getScene().addEventFilter(KeyEvent.KEY_PRESSED, event -> { //your event }); });
источник