How can I force a JLabel to update after setText()?

JDK 1.1.7A and Swing, on Windows NT

In a simple Java application I have a JButton "btnGo" and a JLabel "lblStatus" within a JPanel.

When I click the Go button, I want the status label to immediately display the text "Working...", then I want to
carry out some time-intensive tasks. However, the label text won't update until the tasks have all been completed.

I can simulate this by making the thread sleep for 3 seconds (see code below). It waits three seconds and then
displays the status message.

Is there some way I can force the status label to repaint before the call to Thread.sleep?

Thanks.

class MyActionListener implements ActionListener
{
   public void actionPerformed(ActionEvent event)
   {
      Object object = event.getSource();

      if (object == btnGo)
      {
         lblStatus.setText("Working...");
            
         try {Thread.sleep(3000);}
         catch (Exception e) {}
      }
   }
}
wagtailAsked:
Who is Participating?
 
conickConnect With a Mentor Commented:
Heres a working example:
Notice the Thread.sleep is in a different thread so the event thread can return right away (and change the GUI to "waiting")
The invokeLater method is another thread but it is executed in the event thread when the long task is completed.

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

public class ThreadTest extends JPanel  {
     JLabel label;
     JButton button;
     
     ThreadTest()  {
          setLayout(new BoxLayout(this,BoxLayout.Y_AXIS));
          setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
          JPanel panel1= new JPanel();
          panel1.setLayout(new FlowLayout(FlowLayout.CENTER));
          label= new JLabel("Not Waiting");
          panel1.add(label);
          add(panel1);
          JPanel panel2= new JPanel();
          panel2.setLayout(new FlowLayout(FlowLayout.CENTER));
          button= new JButton("GO");
          button.addActionListener(new TestListener());
          panel2.add(button);
          add(panel2);
     }
     
     public static void main(String args[])  {
          JFrame frame= new JFrame("Thread Test");
          frame.addWindowListener(new WindowAdapter()  {
               public void windowClosing(WindowEvent e)  {
                    System.exit(0);
               }
          });
          frame.setContentPane(new ThreadTest());
          frame.pack();
          frame.setVisible(true);
     }
     class TestListener implements ActionListener  {
          public void actionPerformed(ActionEvent e)  {
               label.setText("Waiting");    
               Thread t= new Thread()  {
                    public void run()  {
                         try {Thread.sleep(3000);}
                         catch (Exception ex) {ex.printStackTrace();}
                         SwingUtilities.invokeLater(new Runnable() {
                                public void run() {
                                          label.setText("Done Waiting");
                               }
                           });
                    }
               };
               t.start();
          }
     }
}
Let me know if you have any questions on how or why it works.
0
 
BillyAbbottCommented:
you could try putting a lblStatus.repaint() call in after the setText line.


0
 
conickCommented:
The GUI does not get updated until the event thread gets done.
(Im pretty sure repaint() or revalidate() will wait also)

Any long process that starts from the event thread should run in a new thread.  That way the GUI can repaint itself if it needs it.  Any change in the GUI from the new thread needs to be done in the event thread (or main thread) (you can use invokeLater()).

If repaint() or revalidate() doesnt work leave a comment if you want an example.
0
The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

 
wagtailAuthor Commented:
Tried repaint() and revalidate() but no luck.

I'd appreciate that example, thanks...

0
 
heyhey_Commented:
you definitely MUST put all the time-intensive tasks inside another Thread.

otherwise you are effectivly blocking the UI thread (even with Thread.sleep())
0
 
wagtailAuthor Commented:
conick, thank you *very* much. This is a truly great solution. Nice one!
0
All Courses

From novice to tech pro — start learning today.