1

I have a comboBox jComboBox1 that contains names of all countries in the world...Upon selection of one of the countries a second combobox jComboBox2 is populated with all the states in the country selected in jComboBox1. Now I want to display a Progress Bar or "Loading..." message when the states in the selected country is populated and closes automatically once it's done.

The code is like this...

 public void actionPerformed(ActionEvent e){
    if(e.getSource()==jComboBox1){
            if(jCombobox1.setSelectedIndex()!=-1){
                   Country country=new Country();
                   country.populateStates(jComboBox2,label,this);
                  //"label" is of type JLabel whose text is is set to show the progress
                  //"this" refers to the current frame to repaint once label is changed
            }
    }
 }

I thought I can use a JLabel in the frame whose visibilty and text can be set using setVisible() and setText. Note that "Country" is a different class and I pass this label to its method populateStates where I use label.setText("Loading details of state:"+state) and do frame.repaint(). (That's why I pass the frame object "this"). Even then, label does not change.

But the only change that appears in the label's initial text after selection of a country is the last text that it is set to, once country's selection is over. Intermediate changes in the label do not appear in the GUI. Why's this happening and what's wrong with my approach? Do I have to use another approach using threads??? If so, how??

Niranjani S
  • 113
  • 1
  • 4
  • 9

2 Answers2

3

First of all, since that seems to be a long task, you need to populate the list of country states OUTSIDE the EDT.

For this, you can use SwingWorker. SwingWorker provides some methods that can be used to give feedback to the user.

But you will have some work to perform to display that feedback.

jfpoilpret
  • 10,449
  • 2
  • 28
  • 32
  • can you give some example code using SwingWorker or related pointers – Niranjani S May 20 '11 at 05:11
  • Examples may be found [here](http://stackoverflow.com/questions/4637215/can-a-progress-bar-be-used-in-a-class-outside-main/4637725#4637725) and [here](http://download.oracle.com/javase/6/docs/api/javax/swing/SwingWorker.html). – trashgod May 20 '11 at 16:03
  • @trashgod I implemented a class extending Swingworker class with a doInBackground that returns some processed data. For this, I have to use get() to retrieve the value. But get() stops all GUI updates. If I delete call to get() and use execute() the gui (label text) shows changes. How to get the return value while updating the GUI at the same time?? – Niranjani S May 21 '11 at 17:03
  • Niranjani S: I've elaborated in an adjacent [answer](http://stackoverflow.com/questions/6056505/how-to-display-a-loading-message-that-closes-automatically-when-processing-i/6083242#6083242). – trashgod May 21 '11 at 17:13
2

I have to use get() to retrieve the value, but get() stops all GUI updates.

Yes, "calling get() on the Event Dispatch Thread blocks all events, including repaints, from being processed until this SwingWorker is complete." Instead, publish() results as they accumulate and process() them on the EDT. See the examples here and here.

Addendum: The get() API shows an example of using a modal dialog in this context. Your PropertyChangeListener can update a JProgressBar in the dialog.

Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045