2

I am trying to learn the intricacies of Swing, and have read a great deal about the Event Dispatch Thread. I understand what is for, however am struggling with the following concept:

I have a JFrame which has been invoked in the normal way:

public class Controller {
GUITopLevel gui = new GUITopLevel(this);

public void initiate() {        
    SwingUtilities.invokeLater(
            new Runnable() {
                @Override
                public void run() {
                    gui.init();
                }
            }
    );
}

public void menuCatch(JMenuItem eventSource) {
    JOptionPane.showMessageDialog(gui.topLevelFrame, eventSource.getActionCommand());
}
}

I want to spawn JDialogs from the gui (code thus):

public class GUITopLevel implements FrontOfHouse {    
JFrame topLevelFrame;

Controller control;

GUITopLevel(Controller c) {
    control = c;
}

@Override
public void GUI() {        
    // Create an action
    MenuAction action = new MenuAction(control);

    // Create the Frame
    topLevelFrame = new JFrame();

    // Create the menu bar
    JMenuBar menuBar = new JMenuBar();
    JMenu file = new JMenu("File");
    JMenu edit = new JMenu("Edit");

    JMenuItem file1 = new JMenuItem();
    JMenuItem file2 = new JMenuItem();
    JMenuItem file3 = new JMenuItem();

    JMenuItem edit1 = new JMenuItem();

    // Set the actions
    file1.setAction(action);
    file2.setAction(action);
    file3.setAction(action);
    edit1.setAction(action);

    // Add the menu items
    file.add(file1);
    file.add(file2);
    file.add(file3);

    edit.add(edit1);

    // Set the text
    file1.setText("Import Diagrams");
    file2.setText("Settings");
    file3.setText("Exit");
    edit1.setText("Cut");
    // Add the menus together
    menuBar.add(file);
    menuBar.add(edit);

    // Set size and add menu bar
    topLevelFrame.setSize(600,400);
    topLevelFrame.setJMenuBar(menuBar);

    topLevelFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

@Override
public void init() {
    GUI();
    //topLevelFrame.pack();
    topLevelFrame.setVisible(true);
}
}

When a menuitem gets clicked, this is called in the controller:

public void menuCatch(JMenuItem eventSource) {
    JOptionPane.showMessageDialog(gui.topLevelFrame, eventSource.getActionCommand());
 }

As gui is the parent container for the JOptionPane, and that has been created with an invokeLater, does this mean that the newly spawned JOptionPane has been called on the EDT or has it been called outside the EDT?

Apologies if this is a duplicate -- I can not seem to find an answer to this question.

mKorbel
  • 109,525
  • 20
  • 134
  • 319
swshaun
  • 384
  • 1
  • 4
  • 12
  • It gets called on the EDT. – Nico Apr 13 '13 at 16:37
  • Thank you. So a call to append a JDialog to the `gui` outside of the thread will be dealt with on the EDT because that is where the `gui` has been created? – swshaun Apr 13 '13 at 16:39
  • That is my understanding of it. If you want to separate the operation, you can work on one of the worker threads. http://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html – Nico Apr 13 '13 at 16:40
  • Grand... I understand now -- worker threads are spawned for non-GUI work as I understand. – swshaun Apr 13 '13 at 16:41
  • 1
    Worker threads are for Swing to avoid GUI lockup whenever you do something that takes a lot of processing. A simple popup operation doesn't really lock your GUI up though. – Nico Apr 13 '13 at 16:43
  • You're very welcome. I probably should have put this as an answer so you could accept it and close this question, but meh. – Nico Apr 13 '13 at 17:01

1 Answers1

2

Your question raises two critical issues:

  • Swing GUI objects should be constructed and manipulated only on the event dispatch thread (EDT). This example is typical, using EventQueue.invokeLater(). Note in particular that the actionPerformed() method of the Timer runs on the EDT. In contrast, your GUITopLevel appears to be instantiated on the initial thread, instead of in your Runnable.

  • A modal dialog will block user input from other windows of the same application, but the EDT continues to run. In the example, add a dialog to the run() method to see the effect.

    public void run() {
        ...
        f.setVisible(true);
        JOptionPane.showMessageDialog(dt, TITLE);
    }
    

See also this Q&A and this Q&A on MVC in Swing.

Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • 2
    [maybe more ideas here](http://stackoverflow.com/questions/8169964/is-mvc-in-swing-thread-safe) – mKorbel Apr 13 '13 at 19:10
  • Thank you. I used `swingUtilities.isEventDispatchThread()` to determine the TopLevelFrame is running on the EDT, and seems it is (returns true). – swshaun Apr 14 '13 at 19:54