我正在使用 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) 可能不会立即影响显示,所以我在初始化后添加了以下内容 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 运行时,它改变了切换的可见性 JLabel 每 100 毫秒一次,这也没有问题。

调用 Swing 组件 事件调度线程 (EDT) 这是一件坏事,因为 Swing 不是线程安全的。我有点惊讶它的效果,而且 它有效的事实可能只是侥幸.

重新粉刷 JPanel?

如果 JLabel的可见性仅在调整大小时受到影响,这可能意味着 JLabel 仅当 JPanel 正在重新粉刷。

要尝试的一件事是致电 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 的更改确实发生在单独的线程上,那么我建议阅读 课:Swing 中的并发Java 教程 了解有关如何使用 Swing 编写性能良好的多线程代码的更多信息。

其他提示

调用setVisible()或删除它应该能正常运行,确保你从事件分派线程,虽然这样做。有在EventQueue的实用方法在该线程运行块。

HTTP:/ /helpdesk.objects.com.au/java/how-do-i-update-my-gui-from-any-thread

您需要在父JPanel的调用重新验证(),如果你需要它的组件进行重新布局。

如果您可以张贴演示该问题的例子,我可以看看它。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top