0

There's a nice discussion on EventQueue.invokeLater() here.

I have a controller class, Master() that loads two UI windows in my application. For example:

public class Master(){

     public Master(){
        aView = new subView();
        bView = new subView();

Where subView extends JFrame and has the following main method:

public class SubView extends JFrame{
    ....

    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new SubView();
            }
        });}
}

Notice that SubView.main() uses the invokeLater(). My question is how can I invokeLater() within master? Something like:

public class Master(){

     public Master(){
        aView = EventQueue.invokeLater(new subView);
        bView = EventQueue.invokeLater(new subView);

It's not this simple because invokeLater does not return anything. Furthermore, because it's "invoked later", the values of aView and bView remain null in Master. Is there anyway to invoke both in the same manner that main() would invoke one of them in the runLater thread?

Community
  • 1
  • 1
Adam Hughes
  • 14,601
  • 12
  • 83
  • 122
  • Do you really need to? If `Master` is always instantiated on the EDT, then there's no need to use `invokeLater`. – davmac Mar 16 '16 at 11:06
  • (Also: is `aView = subView();` supposed to say `aView = new SubView();`?) – davmac Mar 16 '16 at 11:08
  • (Finally: `aView = EventQueue.invokeLater(new subView);` is wrong syntax for basic construction. Probably meant `aView = EventQueue.invokeLater(new SubView());`?) – davmac Mar 16 '16 at 11:09
  • Ya you're right, that's why I specified it was metacode; I knew I was making mistakes. Will try to clean it up, thanks. – Adam Hughes Mar 16 '16 at 12:28

3 Answers3

1

I would use invokeAndWait as you need to wait for the outcome.

SubView aView, bView;

public Master() {
    java.awt.EventQueue.invokeAndWait(new Runnable() {
        public void run() {
            aView = new SubView();
            bView = new SubView();
        }
    });
    // aView and bView will be initialised.
}
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • Thanks. That makes a surprising amount of sense :) Let me try it out and then I will come back and accept the answer. Just for my understanding, this means that aView and bView are running in a shared but separate thread from the main thread, right? – Adam Hughes Mar 11 '16 at 14:49
  • 1
    Ah, so one problem I'm having is aView and bView cann't be accessed by Master(). I need to store them as fields. Let me play with it and report back. – Adam Hughes Mar 11 '16 at 14:55
  • @AdamHughes You either need to store them as fields or you can store them in a collections, or array which is initalised before you start the task. – Peter Lawrey Mar 11 '16 at 20:28
1

It may prove awkward to solve this problem by invoking instances of Runnable. As an alternative use a SwingWorker to update the table models of both the master and detail views. This example may be a useful staring point.

Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
0

Following Peter's suggestion, I did the following:

I created an intermediate Runnable called RunUIThread that returns that exposes the objects aView and bView, so I can return them to my Master program. Peter, do you think this is valid?

    RunUIThread uiThread = new RunUIThread();
    try {
        java.awt.EventQueue.invokeAndWait(uiThread);
    } catch (InterruptedException | InvocationTargetException ex) {
        LOG.error("MasterView interrupted or failed to invoke RunUIThread");
    }
    aView = uiThread.getaView();
    bView = uiThread.getbView();    
Adam Hughes
  • 14,601
  • 12
  • 83
  • 122