Your mistake is quite simple: you are calling (well, you were if it worked) invokeLater
after you are trying to wait
for the result:
synchronized (r) {
try {
…
r.wait(); // <- here you are waiting
} catch (InterruptedException e) {
…
}
}
SwingUtilities.invokeLater(r); // <- never reached, you are waiting above
So the obvious fix would be to call SwingUtilities.invokeLater(r);
first and wait
afterwards.
But that is rather obsolete, there is the method SwingUtilities.invokeAndWait(r);
which does the job of scheduling a Runnable
in the EDT and waiting for its completion. So you don’t need to program your synchronization and notification by yourself.
But note that your lines in your main method following your invokeLater
are manipulating the UI and hence should be placed within the EDT just like the construction of the JFrame
as otherwise you are still violating the Swing’s threading policy and still may get race conditions.
Your main
thread may execute things concurrently to the EDT and it may wait for the UI construction if you wish. But it should not manipulate the UI itself. Such manipulation would also contradict your statement that you want to have the “logical code outside” as manipulating a JFrame
does not belong to “logical code”.