Search code examples
javaswingmodel-view-controllerevent-dispatch-threadcode-duplication

Avoiding code duplication with multiple calls to EventQueue.invokeLater()


So, I have a Java application that uses Swing for building the GUI and implements the MVC design pattern, and because of that I am ending up with a lot of instances of SwingWorker being used in the view to make calls to the controller and a lot of calls to EventQueue.invokeLater() from the controller to the view. This seemed like the way to go because of the single-threaded nature of Swing and MVC best practices, but now I have code that duplicates the following pattern many, many times:

public class MainController{
  private final View someView;
  public void someMethod(Object data){
        // Do stuff with the data; maybe change the model.
        EventQueue.invokeLater( new Runnable(){
             @Override
             public void run() {
                 someView.updateView(Object someObject);  //This is the code that I actually need to execute
             }
        });
  }
}

public class View extends JPanel{ // or whatever
   private final MainController controller;
   public class someListener implements ActionListener{
       public void actionPerformed(ActionEvent e) {
           new SwingWorker<Void,Void>(){
               public Void doInBackground(){
                   controller.someMethod(object);  // This is the code I actually want to execute
                   return null;
               }
           }.execute();
       }
   }
}

I am aware that I can write a method that passes a runnable to a call to EventQueue.invokeLater(), but I would still have to duplicate all the code for implementing a runnable. Most of the pieces of code that I actually need to run, do not have much in common besides the fact that they need to run on the EDT or in a SwingWorker, so extending SwingWorker or implementing Runnable is not going to help. My question is, how do I avoid all this duplication? Is the problem with the design? Or is there a way to make my method calls without all this overhead code?


Solution

  • I finally resolved this issue. Instead of making calls to EventQueue.invokeLater() everywhere in the controllers when updating GUI components, I now wrap the methods in the view that get called by the controllers inside calls to the same. This reduced the size of my controllers by hundreds of lines.