4

I'm just getting to grips with GUI programming in java. Here is a trivial program (from O'Reilly's "Head First Java") which on the face of it looks easy to understand, but there's an aspect of it which I don't follow.

import javax.swing.*;

public class Test {
    public static void main(String[] args) {

    JFrame frame=new JFrame();
    JButton button = new JButton("click me");

    frame.getContentPane().add(button); 
        frame.setSize(300,300);
    frame.setVisible(true);
    }
}

This simple program, when compiled and run, will open a window with a button on it.

What I don't understand is what is happening with the flow of execution. When I run this program, the static main method of the Test class runs, all the commands in main() are executed -- so why doesn't the process terminate after the window appears? Why am I still sitting on what looks like an infinite loop? What is looping?

If I add the line

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

then I find the result even more imcomprehensible. Now, of course, the program terminates once I've closed the window. But again I don't see why. The frame will be on the stack but I don't see where the program flow is and just the existence of something on the stack is not enough to keep the program alive, surely? I'm missing something fundamental which as far as I can see is not covered in the book I'm reading. I am slightly surprised by this -- "Head first Java" has been very good up until now at pointing out subtleties and explaining what is really going on, but doesn't seem to address this point (at least not that I've spotted).

mKorbel
  • 109,525
  • 20
  • 134
  • 319
Kevin Buzzard
  • 537
  • 4
  • 11

2 Answers2

4

why doesn't the process terminate after the window appears?

Because the Java Virtual Machine exits only after all non-daemon threads have finished. While not apparent, there's in fact two threads in your program: the main thread, and the event dispatching thread, which does everything related to the Swing GUI components. The event dispatching thread keeps going as long as any GUI components are visible.

Actually the program, while it may work, is wrong, because you're creating and accessing Swing components from the main thread. You ought to be doing all GUI work in the event dispatching thread. That is, it should be something like:

public static void main(String[] args) {

  EventQueue.invokeLater(new Runnable() {
    JFrame frame=new JFrame();
    JButton button = new JButton("click me");

    frame.getContentPane().add(button); 
    frame.setSize(300,300);
    frame.setVisible(true);
  });
}
Joonas Pulakka
  • 36,252
  • 29
  • 106
  • 169
  • Construction of the GUI in the main thread is acceptable, there just shouldn't be any GUI work after `setVisible`. – Hauke Ingmar Schmidt Feb 05 '12 at 13:59
  • 4
    @his Some code, including that within the Swing implementation calls `java.awt.EventQueue.invokeLater` directly or indirectly. So, construction off the AWT EDT is wrong. Swing really is thread-hostile. – Tom Hawtin - tackline Feb 05 '12 at 14:26
  • 1
    Note to myself: Drop [articles from 1998](http://java.sun.com/products/jfc/tsc/articles/threads/threads1.html) from your memory. Has anyone some bit of information that could push this one out? ;-) – Hauke Ingmar Schmidt Feb 05 '12 at 21:33
  • @his: [Swing package summary of Java 6](http://docs.oracle.com/javase/6/docs/api/javax/swing/package-summary.html#threading) puts it like this: *All Swing components and related classes, unless otherwise documented, must be accessed on the event dispatching thread.* Period. There are [some](http://stackoverflow.com/questions/1796578/which-swing-component-methods-are-thread-safe), mostly text-related methods that are documented thread-safe, but AFAIK no constructors are among them. – Joonas Pulakka Feb 06 '12 at 07:37
  • Thanks a lot for the answer and these comments. I wish I had a more efficient way of teaching myself the nitty-gritty of Java ME than random googling/asking stuff here. On the other hand, I have a working game on my phone that I wrote myself, which is a good start... – Kevin Buzzard Feb 06 '12 at 19:19
1

The Java process terminates when the last non-demon thread dies. Normally there is just one, the main thread. When you display Swing components additional non-demon threads for event dispatching and GUI shotdown are started. Those terminate when the last top-level component gets disposed. In your sample the main thread dies after leaving the main method. You can have a look into the threads with a debugger or jvisualvm from the JDK tools.

The rest of the GUI flow is event driven. When you e.g. click on the frame's close button an event is generated and sent to the appropriate listeners within the event dispatching thread.

Setting JFrame.EXIT_ON_CLOSE as default close operation is like adding a default event listener to the frame. A quite harsh one, it just shuts down the JVM without respect to the rest of the application's state.

Hauke Ingmar Schmidt
  • 11,559
  • 1
  • 42
  • 50