Как использовать Thread.sleep() и setBackground() для создания эффекта вспышки в Swing?

Я хотел бы сделать эффект вспышки: изменив фон (JTextArea) на КРАСНЫЙ -> затем подождите 1 секунду -> вернуться к БЕЛОМУ. Мне нравится это:

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

Но не работает, все что у меня есть это Белый Фон, Красный не вижу.

Что я не так?

Спасибо!


person Huy Than    schedule 10.08.2012    source источник


Ответы (3)


Вместо использования Thread.sleep(...), который может заморозить ваш графический интерфейс, вам следует использовать javax. свинг.Таймер. Более того, любые обновления графического интерфейса должны выполняться в EDT, как очень много говорит @MinhCatVO. Дополнительную информацию по этой теме см. в разделе Параллелизм в 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();
            }
        });
    }
}
person nIcE cOw    schedule 10.08.2012
comment
Спасибо, я думаю, у меня больше нет вопросов о вашем коде. Спасибо за ваше время. - person Huy Than; 11.08.2012
comment
@user1525788 : ДОБРО ПОЖАЛОВАТЬ и ПРОДОЛЖАТЬ УЛЫБАТЬСЯ :-) Мы все здесь, чтобы помогать друг другу, поэтому никогда не хватает времени на этот аспект :-) - person nIcE cOw; 11.08.2012

Потому что этот поток, который вы хотите спать в течение 1 с, не является потоком графического интерфейса. Я думаю, что в 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();
   }
}
person cat_minhv0    schedule 10.08.2012

Это не работает из-за проблемы с потоками. Вам понадобится рабочий поток.

Это должно работать:

            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 так много сообщений об этом. Просто ищите слова.

person Mohayemin    schedule 10.08.2012
comment
SwingWorker предназначен для длительного использования Background tasks, а не для такой мелочи, как замена Colour одного JComponent. - person nIcE cOw; 10.08.2012
comment
@Gagandeep: Ну, я не эксперт в этом. Но я не мог заставить его работать иначе. Вы можете помочь? - person Mohayemin; 10.08.2012
comment
Пожалуйста, взгляните на мой ответ, в нем рассказывается, как это можно сделать с помощью класса javax.swing.TImer. SwingWorker предназначен для ситуаций, которые требуют много времени для завершения, поэтому вместо того, чтобы выполнять такие действия в EDT, мы делаем их в фоновом режиме с его помощью. Поскольку его методы process()/done() по умолчанию автоматически включаются в EDT. - person nIcE cOw; 10.08.2012