java - (Java) JPanel 中出现/消失的 JLabel 仅在调整大小时消失

标签 java resize jframe jpanel repaint

我正在使用 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)上可能不会立即影响显示,因此我在初始化 JLabelJButton 后添加了以下内容。

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正在重新粉刷。

要尝试的一件事是调用 JPanelrepaint方法来查看 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/

相关文章:

uitableview - iOS 8 单元格大小调整

java - 关闭 JFrame 时执行操作

java - 我很难从第一帧调用变量

java - 平板电脑中的 Libgdx 坐标系

java - 如何提取两个有序列表的非交集部分?

java - XPATH - 如何根据其他标签的值选择 1 个标签的值

java - 具有多个框架的 GUI

java - 无法在繁重的进程下更新 Swing 组件

javascript - 我可以像 IE 或 Firefox 一样使用编程来放大网页吗?

html - 调整浏览器窗口大小时如何将绝对定位元素保持在原位