我正在使用 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
来影响可见性。
这可能是线程问题吗?
我的下一个怀疑是,也许线程
不在event dispatch 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
运行,它每100毫秒更改一次JLabel
的可见性,并且这也没有问题。
从 event dispatch thread (EDT) 调用 Swing 组件这是一件坏事,因为 Swing 不是线程安全的。我有点惊讶它能起作用,它起作用的事实可能只是侥幸。
重新绘制JPanel
?
如果 JLabel
的可见性仅在调整大小时受到影响,则可能意味着仅在 JPanel
时才绘制 JLabel
正在重新粉刷。
要尝试的一件事是调用 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 的更改确实发生在单独的线程上,那么我建议阅读 Lesson: Concurrency in Swing来自The Java Tutorials了解有关如何使用 Swing 编写性能良好的多线程代码的更多信息。
关于java - (Java) JPanel 中出现/消失的 JLabel 仅在调整大小时消失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/942883/