0

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?

dramzy
  • 1,379
  • 1
  • 11
  • 25
  • Is your controller multi-threaded? Generally speaking the view shouldn't care, but the controller should make every effort to ensure that it's not update the UI from out side the EDT of course – MadProgrammer Oct 15 '14 at 03:06
  • 2
    You could also use `SwingWoker#publish/process` or `SwingWorker#done` to re-sync the worker with the EDT... – MadProgrammer Oct 15 '14 at 03:07
  • Yes, the controller is multi-threaded. The reason I don't use `SwingWorker`'s other methods is that the controller fetches data from the model and uses it to update the view and I don't want the view to have access to the model nor do I want code that belongs in the controller to be in the view. – dramzy Oct 15 '14 at 03:10
  • I guess the crux of my problem is that I am trying to adhere to MVC while making sure I separate GUI-related (which should run on the EDT) and non-GUI-related tasks (which shouldn't). – dramzy Oct 15 '14 at 03:13
  • 1
    But you could use `done`, for example, to take the results from `doInBackground` and call the `controller` from WITHIN in the context of the EDT...basically doing the same thing you are right now, but without all the "work arounds"? – MadProgrammer Oct 15 '14 at 03:14
  • 2
    I'd be concerned about the controller needing to be multi threaded, that seems wrong to me, but that's just me... – MadProgrammer Oct 15 '14 at 03:15
  • Hmm.. I guess that could work for the cases when the GUI is calling the controller and the controller then updates the GUI. What I meant by the controller being multi-threaded is that sometimes it is being called from a `SwingWorker` thread initiated by the GUI and sometimes it is called by a separate service. – dramzy Oct 15 '14 at 03:19
  • 1
    More information [here](http://stackoverflow.com/a/25556585/230513). – trashgod Oct 15 '14 at 03:28

1 Answers1

0

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.

dramzy
  • 1,379
  • 1
  • 11
  • 25