Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implementing threading in Swing's EDT?

My project is built upon Java's Swing library. It spawns the EDT which displays my GUI (which works correctly).

The entrance to the program, which initializes the EDT:

public final class Main {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Start());
    }

    class Start implements Runnable {
        private Model model = new Model();
        private Controller controller = new Controller(model);
        private View view = new View(controller);

        @Override
        public void run() {
            // Initialize the view and display its JFrame...
        }
    }
}

}

However, when a button / radio box / etc. is clicked within my GUI, the Controller class must perform an action on the model.

My questions are the following:

  • Should I wrap the controller's code in a new SwingWorker?
    • If no, should I wrap my model's code in a new SwingWorker?
  • If I wrap the controller's code with threads, do I need to synchronize the shared state variables within my model?
  • If my model, running on a new thread, notifies my GUI of changes, will this occur on the EDT or on the new thread?

For example:

public class Controller {
    public void updateModel() {
        new SwingWorker<Void, Void>() {
            @Override
            protected Void doInBackground() throws Exception {
                model.somethingSomethingSomething();
            }
        }.execute();
    }
}

public class Model {
    public void somethingSomethingSomething() {
        notifyListeners(); // This is going to notify whichever GUI 
                           // is listening to the model.
                           // Does it have to be wrapped with Swing.invokeLater?
    }
}

public class View {
    // This function is called when the model notifies its listeners.
    public void modelChangedNotifier() {
        button.setText("THE MODEL HAS CHANGED"); // Does this occur on the EDT?
    }
}
like image 750
sdasdadas Avatar asked Nov 21 '25 19:11

sdasdadas


2 Answers

Instead of updating your model from doInBackground(), publish() interim results and update your model from process(), which executes on the EDT. In this example, JTable corresponds to your View and TableModel corresponds to your Model. Note that JTable listens to its own TableModel.

like image 104
trashgod Avatar answered Nov 24 '25 09:11

trashgod


You can read about it here: Improve Application Performance With SwingWorker in Java SE 6. In short: all time consuming operations, which are not affected UI must be done in another thread. To show results of operation you must go back to EDT. For example, if you make database search, you should show a progress bar (usually infinite) and start the search using SwingWorker. To show search results in a table, you must be in EDT. Alternatively you can use foxtrot lib (it allows to make your code more Swing convenient without to redesign it). If your controller code permanently updates the swing widgets you should execute it in EDT or at least perform these updates of UI in EDT (using SwingUtilities.invokeLater, chunk processing in SwingWorker or swing.Timer). So your sample is wrong: model update should be up-to-date in EDT.

like image 36
Sergiy Medvynskyy Avatar answered Nov 24 '25 07:11

Sergiy Medvynskyy



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!