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

0 java resize jpanel jframe repaint

我在Java工作,我在JFrame中有一个JPanel.在那个JPanel中,除其他外,我有一个JLabel,我想让它出现并随意消失.我已经尝试将可见性设置为true/false,在JFrame和JPanel中添加和删除它,并且,在网上查看后,我尝试了验证()和无效地重新生成()无限广告.在这里可以做些什么来解决这个问题?

coo*_*ird 7

通常,调用该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();
      }
    }); 
  }
}
Run Code Online (Sandbox Code Playgroud)

上述程序可以通过单击a来影响可见性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();
Run Code Online (Sandbox Code Playgroud)

随着新的Thread运行,它改变了切换JLabel每100毫秒的可见性,这也没有问题.

事件调度线程(EDT)调用Swing组件是一件坏事,因为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();
Run Code Online (Sandbox Code Playgroud)

如果对GUI的更改确实发生在单独的线程上,那么我建议阅读Lesson:Swing中的并发来自Java教程,以便找到有关如何使用Swing编写良好的多线程代码的更多信息.