Search code examples
javaswingjlabelevent-dispatch-threadthread-sleep

Dynamically updating JLabel to display a changing status msg for processing done on clicking a button


I want to display a status msg that updates dynamically as and when different stages of processing is reached on the processing triggered on clicking a button. Could you pls help on this. Here is the code that I used, but is not working. It always shows the status msg at the end of the function and not intermediate status msgs while executing.

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.*;

import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.*;

import java.net.*;
import java.io.*;

public class MainApplet extends JApplet {
  JButton gstbtn = new JButton("Connect to Gst Hotspot");
  JButton wifibtn = new JButton("Connect to existing Wifi networks");
  JLabel status = new JLabel();
  JPanel toppanel = null, nwConfigDialog = null;
  final JFrame f= new JFrame();
  JTextField ssidTxt;
  JPasswordField pwdTxt;
  JOptionPane opt;

  public void init() {

    gstbtn.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        System.out.println("Gst Hotspot connect workflow triggered");
        setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
        status.setText("");
        toppanel.repaint();
        if(connectToHotSpot()) { //todo: Connect to gst hotspot
                try {
                        status.setText("connected to Local Gst Box Wifi Hotspot");
                        status.repaint();
                        Thread.sleep(20*1000);
                        setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
                } catch(Exception ex) {
                        System.err.println("connect to hotspot: Sleep Exception: " + ex.getMessage());
                }
                //showNwConfigDialog(f);
        } else {
                status.setText("Unable to connect to Local Gst Box Wifi Hotspot");
                setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
        }
      }
    });

    wifibtn.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        System.out.println("Wifi n/w connect workflow triggered");
      }
    });

    toppanel = new JPanel(new GridLayout(4,4,4,4));
    gstbtn.setPreferredSize(new Dimension(5,5));
    wifibtn.setPreferredSize(new Dimension(5,5));
    setContentPane(toppanel);
    getContentPane().add(gstbtn);
    getContentPane().add(wifibtn);
    getContentPane().add(status);
  }
}

Solution

  • It always shows the status msg at the end of the function and not intermediate status msgs while executing.

    This is because this Thread.sleep() call is blocking the Event Dispatch Thread (EDT) which is a single and special thread where Swing components creation/update and event handling is performed, thus causing the GUI be unable to repaint/update itself until this thread is unlocked:

    gstbtn.addActionListener(new ActionListener() {
        ...
        Thread.sleep(20*1000);
        ...
    }
    

    To avoid this issue you should use a SwingWorker to do heavy tasks in a background thread, leaving the EDT free to update the GUI and publishing interim results. There are lot of examples here in SO, just take a look to tag.


    Side note

    Instead of developing a JApplet I'd suggest you to develop a Swing application and use Java Web Start to distribute/launch your application from the web.