2017-02-04 58 views
2

我試圖找到一種方法來檢測(或接收通知)節點已添加到場景並且可見。當節點在場景中可見時檢測

我使用Platform.runLater()將主節點對象創建爲主JavaFx線程並將它們添加到舞臺和場景中。不過,我希望Node對象接收已添加到場景並且可見的通知,例如我希望觸發動畫以啓動。

我似乎無法找到任何屬性或方法添加偵聽器來捕獲此類事件。有什麼建議麼?

回答

2

第三方的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()); 
    } 
} 
+0

我試圖在'最後,你可以手工完成所有這些工作,但它正確地管理聽衆有點難看'之後使用你的代碼。我做'shows.addListener((observable,oldValue,newValue) - > {if(newValue){當節點可見}});'。然而,在我看來,我得到這個事件,但節點還沒有看到。它是真的嗎? –

+0

@Pavel_K據我所知,您可以使用[MCVE]發佈問題。 –

+0

這個解決方案給出了一個問題的答案 - 「如何檢測節點何時成爲場景的一部分?」而不是問題「如何檢測節點何時變得可見」? –

0

您可以將監聽器添加到要添加新節點的容器節點的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); 
+0

有沒有通知/事件從JavaFX的本身節點? – Kerry

+0

將JavaFX節點添加到容器時,JavaFX節點不會發生任何變化 – Buddha

+0

@Buddha上一條評論中的語句不正確:節點具有parentProperty(),該節點將添加到容器時發生更改。另外,'sceneProperty()'可能會改變。 –