我有一个SplitPane,其中有一些显示动态数据的选项卡,因此每当关闭选项卡时,我都想确保所有与数据的连接都已关闭。这是通过侦听选项卡中节点的sceneProperty来完成的,当SceneProperty更改为null时,由于选项卡已关闭,因此连接已关闭。
将选项卡从SplitPane移到其自己的窗口中的可能性将其全部改变了一点。现在,当SceneProperty更改时,计划安排一个任务等待一秒钟,然后检查Node上的SceneProperty是否仍然为空,然后关闭连接。所有这些都是为了避免在将选项卡转移到其自己的窗口时关闭连接,因为在此期间,SceneProperty会非常短暂地变为null。这仍然可以关闭选项卡,但是奇怪的是,当节点具有自己的窗口时,它不起作用,这显然是由于即使关闭窗口后,窗口rootNode上的SceneProperty也不为空。
现在我想知道那怎么可能...?
这基本上是所有代码
// somewhere in the constructor
rootNode.sceneProperty().addListener((observable, oldValue, newValue) -> subscriptionChange(newValue));
private void subscriptionChange(Scene newValue) {
if (newValue == null) {
scheduleUnsubscribeTask();
}
}
private void scheduleUnsubscribeTask() {
UnsubscribeTask unsubscribeTask = new UnsubscribeTask(this::handleUnsubscription);
ScheduledExecutorService scheduledPool = Executors.newScheduledThreadPool(1);
scheduledPool.schedule(unsubscribeTask, TTL_MS, TimeUnit.MILLISECONDS);
}
private void handleUnsubscription() {
if (paneMain.getScene() == null) {
closeConnection();
}
}
答案 0 :(得分:0)
现在我想知道那怎么可能...?
关闭Window
对关联的Scene
无效。 scene
属性也独立于要添加到窗口中的场景;它只是表明节点所在的节点结构的根是否是场景的根。
如果要检查节点是否属于所示场景,我建议使用Bindings.selectBoolean
。否则,您需要(取消)注册/移动3个侦听器(Node.scene
,Scene.window
和Window.showing
属性)。
private BooleanBinding showing;
showing = Bindings.selectBoolean(button.sceneProperty(), "window", "showing");
showing.addListener((o, oldValue, newValue) -> {
if (!newValue) {
scheduleUnsubscribeTask();
}
});
...
private void handleUnsubscription() {
if (!showing.get()) {
closeConnection();
}
}
但是,我建议改为为场景内容引入一些生命周期。这样,您就可以完全控制场景所需的资源。