我試圖找到一種方法來檢測(或接收通知)節點已添加到場景並且可見。當節點在場景中可見時檢測
我使用Platform.runLater()
將主節點對象創建爲主JavaFx線程並將它們添加到舞臺和場景中。不過,我希望Node對象接收已添加到場景並且可見的通知,例如我希望觸發動畫以啓動。
我似乎無法找到任何屬性或方法添加偵聽器來捕獲此類事件。有什麼建議麼?
我試圖找到一種方法來檢測(或接收通知)節點已添加到場景並且可見。當節點在場景中可見時檢測
我使用Platform.runLater()
將主節點對象創建爲主JavaFx線程並將它們添加到舞臺和場景中。不過,我希望Node對象接收已添加到場景並且可見的通知,例如我希望觸發動畫以啓動。
我似乎無法找到任何屬性或方法添加偵聽器來捕獲此類事件。有什麼建議麼?
第三方的JavaFX庫ReactFX有這樣一個機制,這個確切的使用情況在blog引用。總之,你可以做
Val<Boolean> showing = Val.flatMap(node.sceneProperty(), Scene::windowProperty)
.flatMap(Window::showingProperty);
然後當然
showing.addListener((obs, wasShowing, isNowShowing) -> {
if (isNowShowing) {
// node is showing
} else {
// node is not showing
}
});
標準庫有一個版本的這一點,但它是非常寫的不好。 (它不是類型安全的,沒有編譯時檢查屬性是否存在,並且如果「鏈」中的任何屬性都爲null,則會向標準錯誤發出大量不必要的警告,即使API文檔指出這是一個支持使用情況。)如果你想使用標準的JavaFX庫要做到這一點,你可以做
BooleanBinding showing = Bindings.selectBoolean(node.sceneProperty(), "window", "showing");
,然後使用如上結合的方式相同。
最後,你可以做這一切的手,但它變得有點難看妥善管理聽衆:
BooleanProperty showing = new SimpleBooleanProperty();
ChangeListener<Window> windowListener = (obs, oldWindow, newWindow) -> {
showing.unbind();
if (newWindow != null) {
showing.bind(newWindow.showingProperty());
} else {
showing.set(false);
}
};
ChangeListener sceneListener = (obs, oldScene, newScene) -> {
showing.unbind();
if (oldScene != null) {
oldScene.windowProperty().removeListener(windowListener);
}
if (newScene == null) {
showing.set(false);
} else {
newScene.windowProperty().addListener(windowListener);
if (newScene.getWindow() == null) {
showing.set(false);
} else {
showing.bind(newScene.getWindow().showingProperty());
}
}
};
node.sceneProperty().addListener(sceneListener);
if (node.getScene() == null) {
showing.set(false);
} else {
node.getScene().windowProperty().add(windowListener);
if (node.getScene().getWindow() == null) {
showing.set(false);
} else {
showing.bind(node.getScene().getWindow().showingProperty());
}
}
您可以將監聽器添加到要添加新節點的容器節點的children屬性中。
grid.getChildren().addListener((ListChangeListener<? super Node>) change -> {
System.out.println(change.getList().get(0).getTypeSelector());
});
change.getList().get(0)
返回添加到網格對象的第一個節點。
在詹姆斯的評論之後,我擡頭看,是的,從節點的角度來看也是可以的。您可以在節點上監聽parentProeprty的更改。以下代碼顯示瞭如何執行此操作。
Button b = new Button("Test");
b.parentProperty().addListener((observable, oldValue, newValue) -> {
System.out.println("added to a container " + newValue);
});
answerPane.getChildren().add(b);
我試圖在'最後,你可以手工完成所有這些工作,但它正確地管理聽衆有點難看'之後使用你的代碼。我做'shows.addListener((observable,oldValue,newValue) - > {if(newValue){當節點可見}});'。然而,在我看來,我得到這個事件,但節點還沒有看到。它是真的嗎? –
@Pavel_K據我所知,您可以使用[MCVE]發佈問題。 –
這個解決方案給出了一個問題的答案 - 「如何檢測節點何時成爲場景的一部分?」而不是問題「如何檢測節點何時變得可見」? –