【问题标题】:How to use Thread.sleep() and setBackground() to create flash effect in Swing?如何在 Swing 中使用 Thread.sleep() 和 setBackground() 创建 flash 效果?
【发布时间】:2012-08-07 23:30:33
【问题描述】:

我想通过以下方式制作闪光效果: 将(JTextArea 的)背景更改为 RED --> 然后等待 1 秒 --> 回到 WHITE。 我喜欢这样:

JTextArea jTextArea = new JTextArea();
jTextArea.setBackGround(Color.RED);
Thread.currentThread().sleep(1000);
jTextArea.setBackGround(Color.WHITE)

但它不起作用,我只有白色背景,我看不到红色背景。

我错了什么?

谢谢!

【问题讨论】:

    标签: java swing concurrency jtextarea event-dispatch-thread


    【解决方案1】:

    您应该使用javax.swing.Timer,而不是使用Thread.sleep(...),这会冻结您的GUI。此外,正如@MinhCatVO 所说,必须在 EDT 上完成对 GUI 的任何更新。有关该主题的更多信息,请参阅Concurrency in Swing。看看下面的代码,问问你无法理解什么。

    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    
    public class ColouringTextArea
    {
        private JTextArea tarea;
        private Timer timer;
        private Color[] colours = {
                                    Color.RED,
                                    Color.BLUE,
                                    Color.GREEN.darker(),
                                    Color.DARK_GRAY,
                                    Color.MAGENTA,
                                    Color.YELLOW
                                  };
        private int counter = 0;                          
        private ActionListener timerAction = new ActionListener()
        {
            public void actionPerformed(ActionEvent ae)
            {
                if (counter < colours.length)
                {
                    tarea.setBackground(colours[counter]);
                    counter++;
                }
                else
                {
                    tarea.setBackground(Color.PINK);
                    counter = 0;
                }   
            }
        };
    
        private void displayGUI()
        {
            JFrame frame = new JFrame("Colouring JTextArea");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
            JPanel contentPane = new JPanel();
            tarea = new JTextArea(10, 10);
            contentPane.add(tarea);
    
            frame.setContentPane(contentPane);
            frame.pack();
            frame.setLocationByPlatform(true);
            frame.setVisible(true);
    
            timer = new Timer(1000, timerAction);
            timer.start();
        }
    
        public static void main(String... args)
        {
            SwingUtilities.invokeLater(new Runnable()
            {
                public void run()
                {
                    new ColouringTextArea().displayGUI();
                }
            });
        }
    }
    

    【讨论】:

    • 谢谢,我想我对您的代码没有其他问题了。感谢您的宝贵时间。
    • @user1525788 : 最欢迎你并保持微笑 :-) 我们都在这里互相帮助,所以在这方面永远不会缺少时间 :-)
    【解决方案2】:

    因为你想休眠 1 秒的线程不是 GUI 线程。我认为 Swing.Utilities 有一个方法 SwingUtilities.invokeLater()。

    public void class Flash extends Thread {
      JTextArea jtextArea = new JTextArera();
      public void run() {
       SwingUtilities.invokeLater(new Runnable()) {
          jTextArea.setBackground(Color.WHITE);
       }
      }
    }
    
    public void class Main {
       public void main() {
          ...
          Flash fl = new Flash();
          fl.start();
       }
    }
    

    【讨论】:

      【解决方案3】:

      由于线程问题,这不起作用。你需要一个Worker Thread

      这应该可行:

                  SwingWorker<Object, Object> sw = new SwingWorker<Object, Object>() {
                      @Override
                      protected Object doInBackground() throws Exception {
                          SwingUtilities.invokeLater(new Runnable() {
                              @Override
                              public void run() {
                                  jTextArea.setBackground(Color.RED);
                              }
                          });
                          Thread.sleep(1000);
                          SwingUtilities.invokeLater(new Runnable() {
                              @Override
                              public void run() {
                                  jTextArea.setBackground(Color.WHITE);
                              }
                          });
                          return null;
                      }
                  };
      
                  sw.execute();
      

      请注意,Swing 对象上的所有方法都必须从事件调度线程中调用。为此,请使用以下模式:

          SwingUtilities.invokeLater(new Runnable() {
      
              @Override
              public void run() {
                  // Do gui things
              }
          });
      

      了解事件调度线程。 SO中有很多关于此的帖子。只需搜索单词。

      【讨论】:

      • SwingWorker 是用于长时间运行的Background tasks,而不是用于这么小的事情,例如更改单个JComponentColour
      • @Gagandeep:好吧,我不是这方面的专家。但我无法让它工作。你能帮忙吗?
      • 请看我的回答,它告诉你如何使用javax.swing.TImer 类来完成。 SwingWorker 旨在用于需要很长时间才能完成的情况,因此我们不是在 EDT 上执行此类操作,而是在它的帮助下在后台执行它们。因为它的方法 process()/done() 默认情况下自动在 EDT 上。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-07
      • 2016-08-25
      • 1970-01-01
      • 2013-09-27
      • 2021-05-14
      • 2016-07-30
      • 1970-01-01
      相关资源
      最近更新 更多