1

I would like to make flash effect by: changing the background (of a JTextArea) into RED --> then wait for 1 second --> going back to WHITE. I do like this :

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

But it doesn't work, all what I have is the White Background, I don't see the Red one.

What am I wrong?

Thanks!

mKorbel
  • 109,525
  • 20
  • 134
  • 319
Huy Than
  • 1,538
  • 2
  • 16
  • 31

3 Answers3

4

Instead of using Thread.sleep(...), which can freeze your GUI, you should be using javax.swing.Timer. Moreover any updates to the GUI must be done on the EDT, as very much said by @MinhCatVO. For more information on the topic please refer to Concurrency in Swing. Have a look at the below code and ask what is beyond your grasp.

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();
            }
        });
    }
}
nIcE cOw
  • 24,468
  • 7
  • 50
  • 143
  • Thanks, I think I have no further question about your code. Thanks for your time. – Huy Than Aug 11 '12 at 08:58
  • @user1525788 : You're MOST WELCOME and KEEP SMILING :-) We are all here to help each other, so never short of time on that aspect ever :-) – nIcE cOw Aug 11 '12 at 09:38
1

Because that thread u want to sleep for 1s is not GUI thread. I think Swing.Utilities have a method 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();
   }
}
cat916
  • 1,363
  • 10
  • 18
1

This does not work because of threading issue. You need a Worker Thread.

This should work:

            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();

Note that all methods on Swing objects must be called from the Event Dispatch Thread. To do that, use the following pattern:

    SwingUtilities.invokeLater(new Runnable() {

        @Override
        public void run() {
            // Do gui things
        }
    });

Learn about event dispatcher thread. There are so many posts regarding this in SO. Just search the words.

dsh
  • 12,037
  • 3
  • 33
  • 51
Mohayemin
  • 3,841
  • 4
  • 25
  • 54
  • `SwingWorker` is for long running `Background tasks`, not for such a small thing, like changing a `Colour` of a single `JComponent`. – nIcE cOw Aug 10 '12 at 17:04
  • @Gagandeep: Well, I am not an expert on this. But I could not make it work otherwise. Can you help? – Mohayemin Aug 10 '12 at 17:35
  • 2
    Please have a look at my answer, it tells you how it can be done using a `javax.swing.TImer` Class. `SwingWorker` is meant to be used for situations which take long time to finish, so instead of performing such things on the EDT, we do them in background with it's help. Since it's methods `process()/done()` are automatically on the EDT by default. – nIcE cOw Aug 10 '12 at 17:37