1

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!

PeakGen
  • 21,894
  • 86
  • 261
  • 463
  • 2
    First of all, never, ever create, modify or interact with any UI component from any thread other the the Event Dispatching Thread, check out [Concurrency in Swing](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/index.html) for more details. Secondly, I don't see any where where you start a thread so you already be executing within the context of EDT, which means you are blocking it, preventing from updating the UI – MadProgrammer Mar 23 '13 at 06:08
  • @MadProgrammer: Thanks for the reply. Please have a look at the edit – PeakGen Mar 23 '13 at 06:14
  • OK, I managed to solve the issue. Thanks everyone for the replies :) – PeakGen Mar 23 '13 at 06:18
  • I would suggest you use something like a SwingWorker. Can I ask how you got it working? – MadProgrammer Mar 23 '13 at 07:14
  • @MadProgrammer: Yes sure, you are a very good helper so why not? :) Actually, inside my original JLabel, I have used html tags. Same text contained a part which do not have html. I removed the html! Thats all! :D – PeakGen Mar 23 '13 at 08:17
  • 1
    That's what I was afraid of. Your thread is violating the sing thread rules of Swing. You should only ever create/modify/interact with the UI components from the Event Dispatching Thread – MadProgrammer Mar 23 '13 at 08:22
  • @MadProgrammer: I think you are correct. My thread it not closing even the GUI is gone! ahhhhhhhhhhh! I am moving with Timer – PeakGen Mar 23 '13 at 13:07

1 Answers1

4
  • 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();
            }
        });
    }
}
mKorbel
  • 109,525
  • 20
  • 134
  • 319