javafx - 检测节点何时在场景中可见

标签 javafx javafx-8

我正在尝试找到一种方法来检测(或接收通知)节点已添加到场景中并且可见。

我在 JavaFx 主线程之外创建 Node 对象,并使用 Platform.runLater() 将它们添加到舞台和场景中。 .但是,我希望 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
    }
});

标准库有一个版本,但写得很糟糕。 (它不是类型安全的,没有编译时检查属性是否存在,并且如果“链”中的任何属性为空,也会通过管道向标准错误发出许多不必要的警告,即使 API 文档表明这是支持的用例。)如果您想使用标准 JavaFX 库执行此操作,您可以执行
BooleanBinding showing = Bindings.selectBoolean(node.sceneProperty(), "window", "showing");

然后以与上述相同的方式使用绑定(bind)。

最后,您可以手动完成所有这些操作,但是正确管理监听器有点难看:
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());
    }
}

关于javafx - 检测节点何时在场景中可见,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42042212/

相关文章:

java - 为什么在 javafx 的 listview.cellFacoty 方法中调用 super.updateItem(item, empty)?

java - Intellij IDEA 2019.2.4 似乎无法识别 JDK 12 中的 javafx 包

javafx 3d Meshview旋转

Javafx 8 tableview添加行和焦点

java - 长时间运行和阻塞 javafx 任务进度条更新

dialog - 输入验证失败时继续显示对话框

java - 如何在 netbeans 中的 java fxml 应用程序中编译时删除警告

javafx - 如何将 javafx - tableview 大小修复为当前窗口大小

javaFX警报抛出无法捕获的非法状态异常?