Question

I don't understand how to separate the core of my program with the GUI part of my program. Indeed, all the examples on the web say that any GUI action must be executed with SwingUtilities.invokeLater() method.

The problem is I don't understand how can I use this method to handle only my GUI part and how the core and the GUI can communicate.

For instance, I have a class which have the reponsability of the GUI display of some calculations :

public class GUI {
  private JFrame window;

  public GUI() {
    window = null;
  }

  public void createWindow(int width, int height) {
    window = new JFrame();
    ...
    window.setVisible(true);
  }

  public void displayResults(Calcul results) {
    /* Some Swing actions. */
  }
}

and I have the core of my program :

public class Core {
  public static void main(String[] args) {
    GUI gui = new GUI();
    Calcul calculs = new Calcul();

    while (true) {
      /* Make some calculations. */
      /* Put results into calcul. */
      displayResults(calculs);
    }
  }
}

I know that this architecture is not ideal, but I have to use it. My question is, have I to use the EDT to separate the GUI part and the Core part ? And, if the answer is yes, how can I do it ?

If it is possible, I need that the EDT calls are transparent to the user which uses the GUI class.

EDIT:

Does the following transformation of the GUI class has the expected behavior ?

public class GUI {
  private JFrame window;

  public GUI() {
    window = null;
  }

  public void createWindowEDT(final int width, final int height) {
    javax.swing.SwingUtilities.invokeLater(
      new Runnable() {
        public void run() {
          createWindow(width, height);
        }
      }
    );
  }

  private void createWindow(final int width, final int height) {
    window = new JFrame();
    ...
    window.setVisible(true);
  }

  public void displayResultsEDT(final Calcul results) {
    javax.swing.SwingUtilities.invokeLater(
      new Runnable() {
        public void run() {
          displayResultsEDT(results);
        }
      }
    );
  }

  private void displayResults(final Calcul results) {
    /* Some Swing actions. */
  }
}
Was it helpful?

Solution

You can hide the use of the Event Dispatch Thread (EDT) in your GUI class. Its only the interaction with the Swing components that needs to be on the EDT given it's the Swing components that aren't normally thread-safe.

There's no need for any synchronization in the GUI class given there's only the main application thread going to call GUI.displayResults(Calcul), though if this changes you may want to synchronize this method or take other steps to avoid threading errors.

public class GUI
{
  ...

  public void displayResults(Calcul results) 
  {
    SwingUtils.invokeLater(
      new Runnable()
      {
        public void run()
        {
          /* Some Swing actions. */
        }
      }
    );
  }
}

OTHER TIPS

To put your GUI code in EDT, use SwingUtilities class. You have to pass a Runnable instance to invokeLater() method.

You should create your GUI (call GUI constructor) in the EDT too.

public static void main(String[] args) {

    GUI gui = null;
    Calcul calculs = new Calcul();

    SwingUtilities.invokeLater(
        new Runnable() {
             public void run() {
               gui = new GUI();
             }});


    while (true) {
    /* Make some calculations. */
    /* Put results into calcul. */
    javax.swing.SwingUtilities.invokeLater(
        new Runnable() {
             public void run() {
                 gui.displayResults(calculs);
             }});
    }
  }

The problem is you cannot run your calculation and your GUI in the same thread. If you do this, your GUI will freeze while your code is doing the number crunching. One approach is to run your calculations in a separate thread, then from that thread using SwingUtilities.invokeLater() signal your GUI that it should update itself. For example:

public static void main(String[] args) {
    final GUI myGUI = new GUI();

    Thread workThread = new Thread(new Runnable() {
        public void run() {
            // do calculations

            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    // update GUI
                    myGUI.updateMyResults();
                }
            });
        }
    });

    workThread.start();
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top