【发布时间】:2017-09-04 11:00:30
【问题描述】:
我需要检测一个节点当前是否正在显示。 IE。如果我的节点在 TabPane 中,我需要知道它是否在选定的选项卡中。
在示例中,我想知道 HBox 何时显示。Node 的 visibleProperty 和 managedProperty,似乎对我没有帮助:
public class VisibleTest extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
TabPane tabpane = new TabPane();
tabpane.getTabs().add(new Tab("Tab1", new Label("Label1")));
HBox hbox = new HBox(new Label("Label2"));
hbox.setStyle("-fx-background-color: aquamarine;");
hbox.visibleProperty().addListener((observable, oldValue, newValue) -> {
System.out.println("Hbox visible changed. newValue: " + newValue);
});
hbox.managedProperty().addListener((observable, oldValue, newValue) -> {
System.out.println("Hbox managed changed. newValue: " + newValue);
});
Tab tab2 = new Tab("tab2", hbox);
tabpane.getTabs().add(tab2);
primaryStage.setScene(new Scene(tabpane));
primaryStage.setWidth(600);
primaryStage.setHeight(500);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
我知道,可以在选项卡的selectedProperty 状态下收听,但这并不能解决我真正的问题。
Node.impl_isTreeVisible() 做我想做的事,但这是废弃的 API。
有什么想法吗?
- - - - - - - - - - - - - - - - - - 更新 - - - - - - - --------
我意识到上面的代码示例并不能很好地解释我想要完成的工作。
下面是一些 Swing 代码,它展示了我想要在 JavaFX 中完成的工作。检测 JComponent/Node 是否可见/显示,并根据该状态启动或停止后台进程。如果它是一个 javaFX 类,构造函数会是什么样子。
public class SwingVisible extends JComponent {
String instanceNR;
Thread instanceThread;
boolean doExpensiveStuff = false;
public SwingVisible(String instanceNR) {
this.instanceNR = instanceNR;
this.setLayout(new FlowLayout());
this.add(new JLabel(instanceNR));
instanceThread = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (doExpensiveStuff) {
/*
* do expensive stuff.
*/
System.out.println(instanceNR + " is visible " + isVisible());
}
}
}
});
/*
* How to do this in FX?
*/
addComponentListener(new ComponentAdapter() {
@Override
public void componentShown(ComponentEvent e) {
if (!instanceThread.isAlive()) {
instanceThread.start();
}
doExpensiveStuff = true;
}
@Override
public void componentHidden(ComponentEvent e) {
doExpensiveStuff = false;
}
});
}
public static void main(String[] args) {
/*
* This block represents code that is external to my library. End user
* can put instances of SwingVisible in JTabbedPanes, JFrames, JWindows,
* or other JComponents. How many instances there will bee is not in my
* control.
*/
JTabbedPane jtp = new JTabbedPane();
jtp.add("tab1", new SwingVisible("1"));
jtp.add("tab2", new SwingVisible("2"));
jtp.add("tab3", new SwingVisible("3"));
JFrame f = new JFrame("test");
f.setContentPane(jtp);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(300, 300);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
选择tab1时的输出:
1 可见为真
1 可见 true
1 可见 true
...
选择tab2时的输出:
2 可见为真
2 可见真
2 可见真
...
【问题讨论】:
-
如果tab2正在显示,你不知道hbox正在显示吗?
-
这可能是真的,但是如果您使用我的原始答案,您就会知道选择 tab2 时 hbox 正在屏幕上显示/可见。
-
HBox的可见性相当于它所在标签的 selected 属性,为什么不使用呢? -
正确的做法是使用标签的
selectedProperty()。任何其他方法的问题在于它依赖于选项卡窗格的实现。目前,选项卡窗格的工作方式是将所有选项卡的内容布局在一个窗格中,并根据是否选择选项卡使每个选项卡的内容可见或不可见。但是,不能保证此实现将保留在未来的版本中:因此您唯一的选择是响应选项卡的 selected 属性。 -
您说“这不是真正的问题”。我们非常感谢您为制作一个最小、完整的示例所做的努力,但它似乎并不能完全描述您要解决的问题。看看你是否能找出一个描述实际问题的例子。请注意,知道“标签何时可见”非常困难,因为您真的需要知道它及其所有祖先是否可见,如果它是显示在正在显示的窗口中的场景的一部分,以及如果在其顶部显示任何其他节点。