Search code examples
javaswingjlabelrepaintevent-dispatch-thread

Swing - revalidate of UI not happening


I have a JButton and a JLabel. The code is written so that when the user clicks on the button, the action performed changes the text of the JLabel and starts doing some stuff. However, in reality, Label text doesn't change until the stuff being done is finished.

This is the code in the button action

lbl.setText("Doing");
revalidate();
DoStuff();

The label's text doesn't change until the method DoStuff returns. I know revalidate just schedules a call to paint so I think that this is because the paint thread never gets a slice to change the text.

How do I fix this?

Here is a repro program. Instead of DoStuff(), I have a while(true); which simulates the same behaviour. If you run this program, you will have to kill it to get it to exit.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Util1
{
    public static void main(String[] args)
    {
        new Util1();
    }

    public Util1()
    {
        EventQueue.invokeLater(new Runnable() 
        {
            public void run() 
            {

                JFrame frame = new JFrame("Test");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new ExamplePane());

                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true); 
            }
        });
    }


    protected class ExamplePane extends JPanel 
    {
        public ExamplePane() 
        {
            final JPanel panel = new JPanel(new GridBagLayout());

            JButton btn = new JButton("Do Stuff");
            final JLabel lbl = new JLabel("Status");
            add(btn);
            add(lbl);

            btn.addActionListener(new ActionListener() 
            {
                public void actionPerformed(ActionEvent ae) 
                {
                    lbl.setText("Doing");
                    revalidate();
                    while(true);
                }
            });

        }            
    }        
}

Solution

  • The thing is, that actions in public void actionPerformed(ActionEvent ae) method execute in Swing thread. The changes are not shown till all of actions are executed. You can, for example, perform your doStaff method in another thread. For more details, see this topic. I had the same problem.