PeakGen
PeakGen

Reputation: 23035

Unable to update JDialog GUI inside a thread

Please have a look at the following code

private class EmergencyAlertNotifier implements Runnable, ActionListener
    {
        JDialog dialog = new JDialog();
        int number=0;

        JLabel message;
        JButton yes,no;

        String messageStr;

        public EmergencyAlertNotifier()
        {
            dialog.setLayout(new BorderLayout());

            //The JLabel which will display the number of seconds left
            //before alerting emergency services
            message = new JLabel();


             messageStr="number";

            yes = new JButton("OK");
            yes.addActionListener(this);
            no = new JButton("Cancel");
            no.addActionListener(this);

            JPanel btnPanel = new JPanel();
            btnPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
            btnPanel.add(yes);
            btnPanel.add(no);

            dialog.add(message,"Center");
            dialog.add(btnPanel,"South");

            dialog.setTitle("Ready To Notify Emergency Fire Services");
            dialog.setVisible(true);
            dialog.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        }

        @Override
        public void run() 
        {
            for(int i=10;i>0;i--)
            {
                message.setText(messageStr+i+" Sec.");


                try
                {
                    Thread.sleep(1000);
                }
                catch(Exception e)
                {
                    e.printStackTrace();
                }
            }


        }

        @Override
        public void actionPerformed(ActionEvent e) 
        {
            if(e.getSource()==yes)
            {

            }
            else
            {
                dialog.dispose();
            }
        }

    }

Thread is started outside the above class

 new Thread(new EmergencyAlertNotifier()).start();

I am trying to update the JLabel with the changing numbers inside the thread. But instead, the JLabel is not coming to the GUI. Why is that? Please help!

Upvotes: 1

Views: 1288

Answers (1)

mKorbel
mKorbel

Reputation: 109823

  • there are a few issue in your code, with Concurency in Swing,

  • please I can't comment that somehow,

  • untill SwingWorker will implemented in official API, Runnable#Thread was standard workaround for Workers Thread,

  • for production code to use Runnable#Thread instead of SwingWorker (my view, disagree with black hole implemented in API)

  • output from Runnable#Thread to the Swing GUI required usage of invokeLater, for thread_safe (setText, append... , especially there were chnages in Java7 in compare with Java6) methods too

  • use util.Timer for count_down, instead of Thread.sleep()

modified code, works as expected

import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class EmergencyAlertNotifier implements Runnable, ActionListener {

    private JDialog dialog = new JDialog();
    private int number = 0;
    private JLabel message;
    private JButton yes, no;
    private String messageStr;
    private boolean runProcess = true;

    public EmergencyAlertNotifier() {
        dialog.setLayout(new GridLayout());
        //The JLabel which will display the number of seconds left
        //before alerting emergency services
        message = new JLabel();
        messageStr = "number";
        yes = new JButton("OK");
        yes.addActionListener(this);
        no = new JButton("Cancel");
        no.addActionListener(this);
        JPanel btnPanel = new JPanel();
        btnPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
        btnPanel.add(yes);
        btnPanel.add(no);
        dialog.add(message, "Center");
        dialog.add(btnPanel, "South");
        dialog.setTitle("Ready To Notify Emergency Fire Services");
        dialog.pack();
        dialog.setVisible(true);
        dialog.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        new Thread(this).start();
    }

    @Override
    public void run() {
        while (runProcess) {
            for (int i = 10; i > 0; i--) {
                message.setText(messageStr + " " + i + " Sec.");
                try {
                    Thread.sleep(1000);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            runProcess = false;
        }
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == yes) {
        } else {
            dialog.dispose();
        }
    }

    public static void main(String args[]) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                EmergencyAlertNotifier ean = new EmergencyAlertNotifier();
            }
        });
    }
}

Upvotes: 4

Related Questions