Dimos Fotiadis Dimos Fotiadis - 4 years ago 228
Java Question

Jbutton flash between two backround colors

My problem: Efficient way for the program to delay in my scenario.

My Scenario:
I am making a quiz game for a short project, long story short. A question is answered when the user presses one of four Jbuttons having an answer on them. Then my quizengine class calls the paintbutton method showed here. After that it proceeds to call some other methods responsible for making the next question appear. Now what I want is to make the button change between two colors with decreasing time intervals.

What have I tried so far:
First I placed a JoptionPane between the paintbutton method and the method that changes the interface to the next question just to see if the button would change color. It did successfully. Of course that wasn't my intention, I wanted just a time interval.
Then I tried using Thread.Sleep. Although the program would wait before changing to the next question, the color change was not visible.
Finally I tried an implementation of the Timer thingy (probably not correctly) which although it changed the color the program went ahead and proceeded to the next question.

My want to be code

/* Paints the button pressed red or green
* Green if the anwser is correct red if
* its false
* @param int bnr the number of the button
* @param boolean corr true if correct false if false :D
public static void paintbutton(int bnr,boolean corr) {
for (int i=10;i>1;i--){
//wait for i*100 milliseconds

Answer Source

Let's start with some basics. Swing is single threaded, meaning you must never block or execute long running code within the context of the Event Dispatching Thread, this will make the UI freeze and the user upset

Swing is NOT thread safe, this means that you should never create or update the UI from outside of the context of the EDT.

This leads you into a problem. You want to, after a some small delay, update the UI.

Lucky for you, there are at least two possibilities, a Swing Timer or a SwingWorker.

A Swing Timer is relatively simple, but doesn't really provide a means to generate a variable delay between updates. A SwingWorker is more complex, but gives you the control to basically do what you want.

Both of these (can) "wait" outside of the EDT, but both provide means by which you can push updates to the EDT safely.

For example...


import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class BlinkyTheButton {

    public static void main(String[] args) {
        new BlinkyTheButton();

    public BlinkyTheButton() {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {

                JFrame frame = new JFrame("Testing");
                frame.add(new TestPane());

    public class TestPane extends JPanel {

        private JButton blinky;

        public TestPane() {
            blinky = new JButton("Blinky");
            blinky.addActionListener(new ActionListener() {
                private BlinkWorker worker;
                public void actionPerformed(ActionEvent e) {
                    if (worker == null || worker.getState() == SwingWorker.StateValue.DONE) {
                        worker = new BlinkWorker(blinky, Color.RED);
                        worker.addPropertyChangeListener(new PropertyChangeListener() {
                            public void propertyChange(PropertyChangeEvent evt) {
                                SwingWorker worker = (SwingWorker) evt.getSource();
                                if ("state".equals(evt.getPropertyName())) {
                                    if (worker.getState() == SwingWorker.StateValue.DONE) {
                                        // this is where you would then call the method to
                                        // update the state for a new question
            setLayout(new GridBagLayout());

        public Dimension getPreferredSize() {
            return new Dimension(200, 200);

        public class BlinkWorker extends SwingWorker<Void, Color> {

            private JButton btn;
            private Color color;
            private Color normal;

            public BlinkWorker(JButton btn, Color color) {
                this.btn = btn;
                normal = btn.getBackground();
                this.color = color;

            protected Void doInBackground() throws Exception {
                for (int index = 10; index > 1; index--) {
                    Thread.sleep(index * 100);
                    Thread.sleep(index * 100);
                return null;

            protected void process(List<Color> chunks) {
                Color color =  chunks.get(chunks.size() - 1);




Have a look at Concurrency in Swing, How to use Swing Timers and Worker Threads and SwingWorker for more details

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download