14

What's the programmatic equivalent of clicking the close (x) button in the upper right corner of a JFrame?

There's the dispose() method but that's not the same thing, since a JFrame can be set to do several different things upon closing (not to mention if there's a WindowListener involved)

tshepang
  • 12,111
  • 21
  • 91
  • 136
Jason S
  • 184,598
  • 164
  • 608
  • 970

3 Answers3

16

You tell the component to dispatch an event. In this case, you want it do dispatch a Window Closing event.

private void exit() {
    this.dispatchEvent(new WindowEvent(this, WindowEvent.WINDOW_CLOSING));
}
jjnguy
  • 136,852
  • 53
  • 295
  • 323
  • Cool, that's what I was looking for. I think you need to use Swing.invokeLater() though, to make sure it's on the event dispatch thread. – Jason S Oct 08 '10 at 18:42
  • @Jason, if this is being called from a Swing component, then it is already on the EDT. That is why you never want to do long calculations inside of a Swing component. (Because they would block the EDT) – jjnguy Oct 08 '10 at 18:53
  • Right. But I want to call it from another component. (I used `public void closeWindow()` as my signature.) – Jason S Oct 08 '10 at 19:03
2

When you hit the x on a JFrame, the system can be set to do various things. The default is that the window is simply hidden with setVisible(false) I believe.

You can set a frame to do different things on close--you can have it dispose, hide or call code based on setDefaultCloseOperation. Here are the options:

DO_NOTHING_ON_CLOSE: Don't do anything; require the program to handle the operation in the windowClosing method of a registered WindowListener object.

HIDE_ON_CLOSE: Automatically hide the frame after invoking any registered WindowListener objects.

DISPOSE_ON_CLOSE: Automatically hide and dispose the frame after invoking any registered WindowListener objects.

EXIT_ON_CLOSE: Exit the application using the System exit method. Use this only in applications.

But I think what you are after is setVisible(false).

Bill K
  • 62,186
  • 18
  • 105
  • 157
0

You have to insert the call into the AWT message queue so all the timing happens correctly, otherwise it will not dispatch the correct event sequence, especially in a multi-threaded program.

public void closeWindow()
{
    if(awtWindow_ != null) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                awtWindow_.dispatchEvent(new WindowEvent(awtWindow_, WindowEvent.WINDOW_CLOSING));
            }
        });
    }
}
peterk
  • 5,136
  • 6
  • 33
  • 47
  • This approach _seems_ to work. The right user experience is obtained. But, is this the proper way for the AWT event handling protocol? Within one event handler, if we need to dispatch another event, are we _supposed_ to enqueue with a later Runnable? Or, no, internally `dispatchEvent` takes proper care of deferring event handling until after the conclusion of the current event? (I do not know AWT's event handling protocol!) – Lonnie Dec 12 '22 at 14:44