(Java) JPanel 中出现/消失的 JLabel 仅在调整大小时消失
题
我正在使用 Java,并且 JFrame 中有一个 JPanel。在该 JPanel 中,除其他外,我有一个 JLabel,我想让它随意出现和消失。我尝试将可见性设置为 true/false,在 JFrame 和 JPanel 中添加和删除它,并且在网上查看后,我尝试了无限次的 validate() 和 revalidate() 。这里可以做什么来解决这个问题呢?
解决方案
一般来说,调用 setVisible
方法足以使 Swing 组件显示或隐藏。
为了确保它有效,我尝试了以下操作:
public class Visibility {
private void makeGUI() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JLabel l = new JLabel("Hello");
final JButton b = new JButton("Hide Label");
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
l.setVisible(false);
}
});
f.getContentPane().setLayout(new BorderLayout());
f.getContentPane().add(l, BorderLayout.CENTER);
f.getContentPane().add(b, BorderLayout.SOUTH);
f.setSize(200, 200);
f.setLocation(200, 200);
f.validate();
f.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Visibility().makeGUI();
}
});
}
}
上面的程序能够通过单击来影响可见性 JButton
.
这可能是线程问题吗?
我的下一个怀疑是,也许 Thread
那不是在 事件调度线程 (EDT) 可能不会立即影响显示,所以我在初始化后添加了以下内容 JLabel
和 JButton
.
Thread t = new Thread(new Runnable() {
public void run() {
while (true) {
b.setVisible(!b.isVisible());
try {
Thread.sleep(100);
} catch (InterruptedException e) { /* Handle exception /* }
}
}
});
t.start();
随着新 Thread
运行时,它改变了切换的可见性 JLabel
每 100 毫秒一次,这也没有问题。
调用 Swing 组件 事件调度线程 (EDT) 这是一件坏事,因为 Swing 不是线程安全的。我有点惊讶它的效果,而且 它有效的事实可能只是侥幸.
重新粉刷 JPanel
?
如果 JLabel
的可见性仅在调整大小时受到影响,这可能意味着 JLabel
仅当 JPanel
正在重新粉刷。
要尝试的一件事是致电 JPanel
的 repaint
方法查看是否可见 JLabel
会改变。
但如果主要原因是 EDT 中的线程试图更改 GUI,则此方法似乎只是一种创可贴。(正如注释一样, repaint
方法是线程安全的,因此可以由非 EDT 线程调用,但依赖于 repaint
是一种解决方法而不是解决方案。)
尝试使用 SwingUtilities.invokeLater
最后,我可能会尝试的是 SwingUtilities.invokeLater
方法,如果它想影响 GUI,则可以从与 EDT 分开运行的线程中调用(并且只能调用)该方法。
所以,较早的 Thread
示例应写为:
Thread t = new Thread(new Runnable() {
public void run() {
while (true) {
try {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
b.setVisible(!b.isVisible());
}
});
} catch (Exception e1) { /* Handle exception */ }
try {
Thread.sleep(100);
} catch (InterruptedException e) { /* Handle exception */ }
}
}
});
t.start();
如果对 GUI 的更改确实发生在单独的线程上,那么我建议阅读 课:Swing 中的并发 从 Java 教程 了解有关如何使用 Swing 编写性能良好的多线程代码的更多信息。
其他提示
调用setVisible()或删除它应该能正常运行,确保你从事件分派线程,虽然这样做。有在EventQueue的实用方法在该线程运行块。
HTTP:/ /helpdesk.objects.com.au/java/how-do-i-update-my-gui-from-any-thread
您需要在父JPanel的调用重新验证(),如果你需要它的组件进行重新布局。
如果您可以张贴演示该问题的例子,我可以看看它。