当节点在场景中可见时检测 [英] Detect When A Node is Visible in a Scene
问题描述
我正在尝试找到一种检测(或接收通知)节点已添加到场景并且可见的方法。
I am trying to find a way to detect (or receive notification) that a Node has been added to a Scene and is visible.
我正在创建Node对象关闭主JavaFx线程并使用 Platform.runLater()
将它们添加到舞台和场景中。但是我希望Node对象接收已添加到Scene中并且可见的通知,例如我希望触发动画启动。
I am creating Node objects off the main JavaFx thread and add them to the Stage and Scene using Platform.runLater()
. However I would like the Node object to receive notification that is has been added to the Scene and is visible, for example I wish to trigger an animation to start.
我可以似乎找不到任何属性或方法来添加一个侦听器来捕获这样的事件。有什么建议吗?
I can't seem to find any property or method to add a listener to capture such an event. Any suggestions?
推荐答案
第三方JavaFX库 ReactFX 有一个机制,这个确切的用例在博客。简而言之,你可以做到
The third-party JavaFX library ReactFX has a mechanism for this, and this exact use case is cited in the blog. In short, you can do
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
}
});
标准库有一个版本,但编写得非常糟糕。 (它不是类型安全的,没有编译时检查属性是否存在,并且如果链中的任何属性为空,也会将大量不必要的警告传递给标准错误,即使API文档指示这是一个支持的用例。)如果你想用标准的JavaFX库做,你可以做
The standard library has a version of this, but it is very badly written. (It is not typesafe, has no compile-time checking that the properties exist, and also pipes a lot of unnecessary warnings to standard error if any of the properties in the "chain" are null, even though the API docs indicate this is a supported use case.) If you want to do this with the standard JavaFX library, you can do
BooleanBinding showing = Bindings.selectBoolean(node.sceneProperty(), "window", "showing");
然后以与上面相同的方式使用绑定。
and then use the binding the same way as above.
最后,您可以手动完成所有这些操作,但是正确管理听众会有点难看:
Finally, you could do all this by hand, but it gets a bit ugly to manage the listeners properly:
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());
}
}
这篇关于当节点在场景中可见时检测的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!