Я полагаю, что использование слушателя, как показано в ответе @ MS , вероятно, лучший и самый простой способ реагировать на изменения сцены. Тем не менее, вы спрашиваете, как создать «пользовательское событие», которое вы можете запустить при изменении сцены; под «событием» я предполагаю, что вы имеете в виду подкласс javafx.event.Event
. Поэтому, хотя я рекомендую придерживаться простого слушателя, вот пример пользовательского события.
Во-первых, вам нужен собственный класс события:
import javafx.event.Event;
import javafx.event.EventType;
import javafx.scene.Scene;
import javafx.stage.Window;
public class SceneChangedEvent extends Event {
public static final EventType<SceneChangedEvent> SCENE_CHANGED =
new EventType<>(Event.ANY, "SCENE_CHANGED");
public static final EventType<SceneChangedEvent> ANY = SCENE_CHANGED;
private transient Window window;
private transient Scene oldScene;
private transient Scene newScene;
public SceneChangedEvent(Window window, Scene oldScene, Scene newScene) {
super(window, window, SCENE_CHANGED);
this.window = window;
this.oldScene = oldScene;
this.newScene = newScene;
}
public Window getWindow() {
return window;
}
public Scene getOldScene() {
return oldScene;
}
public Scene getNewScene() {
return newScene;
}
}
Я не уверен, какую информацию вы Я хочу добавить событие, поэтому я просто добавил источник Window
, а также старый и новый Scene
s. Если вас интересует ANY = SCENE_CHANGED
, я просто следую шаблону, используемому javafx.event.ActionEvent
(который также имеет только один тип события).
Тогда вам просто нужно запустить событие, когда сцена меняется. Чтобы реализовать это, вам все еще понадобится слушатель изменений. Как вы упомянули о желании расширить Stage
, вот пример этого:
import javafx.beans.NamedArg;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.event.EventHandler;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class CustomStage extends Stage {
private final ObjectProperty<EventHandler<? super SceneChangedEvent>> onSceneChanged =
new SimpleObjectProperty<>(this, "onSceneChanged") {
@Override
protected void invalidated() {
setEventHandler(SceneChangedEvent.SCENE_CHANGED, get());
}
};
public final void setOnSceneChanged(EventHandler<? super SceneChangedEvent> handler) {
onSceneChanged.set(handler);
}
public final EventHandler<? super SceneChangedEvent> getOnSceneChanged() {
return onSceneChanged.get();
}
public final ObjectProperty<EventHandler<? super SceneChangedEvent>> onSceneChangedProperty() {
return onSceneChanged;
}
public CustomStage() {
this(StageStyle.DECORATED);
}
public CustomStage(@NamedArg(value = "style", defaultValue = "DECORATED") StageStyle style) {
super(style);
sceneProperty().addListener((obs, ov, nv) -> fireEvent(new SceneChangedEvent(this, ov, nv)));
}
}
Это позволит вам реагировать на изменение сцены, используя любое из следующего:
CustomStage stage = new CustomStage();
// addEventFilter/addEventHandler
stage.addEventFilter(SceneChangedEvent.SCENE_CHANGED, e -> { ... });
stage.addEventHandler(SceneChangedEvent.SCENE_CHANGED, e -> { ... });
// setOnSceneChanged
stage.setOnSceneChanged(e -> { ... });
Keep in имейте в виду, что событие будет нацелено только на экземпляр CustomStage
. Другими словами, только обработчики событий, добавленные к экземпляру CustomStage
, будут уведомлены о событии. И, как вы можете видеть, это гораздо сложнее, чем просто добавить прослушиватель изменений в свойство scene
Stage
.