views:

2307

answers:

4

Is there a way to close a JDialog through code such that the Window event listeners will still be notified? I've tried just setting visible to false and disposing, but neither seem to do it.

thanks, Jeff

A: 

Untested suggestion:

Have you tried getWindowListeners() and then iterating around to fire windowClosed() to each of the WindowListeners?

EDIT: the above suggestion is wrong. Keeping it for posterity.

I'm afraid calling dialog.dispose() works fine for me in my simple example.

Grundlefleck
A: 

Dispatch a windowClosing event to the Window. Check out the ExitAction example from the Closing an Application entry.

camickr
How do people learn anything if you don't give a reason for the down vote?
camickr
It wasn't me that downvoted it, but perhaps it's because it looks as though you didn't try to understand Jeff's problem, you just found linked to your most-likely-related existing blog post. The fact that you've posted two complaints about Jeff not liking your answer without any further attempt to find out why it's not working for him doesn't make the answer itself look any more attractive.
David Moles
I agree I could be out in left field but, my comment about one of us not understanding the other indicates I've looked at this several times trying to make sure I understand the question. My other comments are designed to have Jeff take another look at my suggestions. I still maintain I have a 1 line solution for his problem on creating images of a non displayed panel.
camickr
In my experience asking questions (or presenting alternative hypotheses) about the original question is more effective than just looking at it harder and/or suggesting the poster hasn't looked at your answer hard enough. You also seem to be fond of posting comments (like this one) complaining about the poster's failure to appreciate your answers to other questions, and I'm not sure who that's helping. But hey, your rep's 40% higher than mine with only 28% more answers, so clearly the downvotes can't be weighing you down too much.
David Moles
Its my experience that people like to be "spoon fed" the answer. So when presented the option of "posted code" versus "following a link and doing some reading" the former is usually choosen. So my comments are designed to nudge the poster into actually reading the link. By the way my suggestion results in both a windowClosing and WindowClosed event being generated when DISPOSE_ON_CLOSE is used.
camickr
+2  A: 

I don't seem to have your problem. When I use the code below windowDeactivated() is called for either setVisible( false ) or dispose() and windowClosed() is also called for dispose().

ClosingDialog.java:

public class ClosingDialog extends JDialog {
    public ClosingDialog(Frame owner, String title, boolean modal) {
        super(owner, title, modal);
        JPanel contentPanel = (JPanel) this.getContentPane();

        JButton setVisButton = new JButton("setVisible( false )");
        setVisButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                ClosingDialog.this.setVisible(false);
            }
        });

        JButton disposeButton = new JButton("dispose()");
        disposeButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                ClosingDialog.this.dispose();
            }
        });

        contentPanel.setLayout(new FlowLayout());

        contentPanel.add(setVisButton);
        contentPanel.add(disposeButton);

        this.addWindowListener(new WindowListener() {
            public void windowActivated(WindowEvent e) {
                System.out.println("windowActivated");
            }

            public void windowClosed(WindowEvent e) {
                System.out.println("windowClosed");
            }

            public void windowClosing(WindowEvent e) {
                System.out.println("windowClosing");
            }

            public void windowDeactivated(WindowEvent e) {
                System.out.println("windowDeactivated");
            }

            public void windowDeiconified(WindowEvent e) {
                System.out.println("windowDeiconified");
            }

            public void windowIconified(WindowEvent e) {
                System.out.println("windowIconified");
            }

            public void windowOpened(WindowEvent e) {
                System.out.println("windowOpened");
            }
        });

        this.setSize(300, 300);
    }
}
Joseph Gordon
All windowDeactivated means is that is has lost focus. You don't know for sure if the window is actually closing. Generally WindowListeners will listen for the window closing event so they can do some special processing on a close.
camickr
Yes, I tried with windowClosing and did not receive that event.
Jeff Storey
Which is why I gave my solution 5 hours ago.
camickr
Typo: The action for `disposeButton` should call `ClosingDialog.this.dispose()`, not `setVisible(false)` again. If you do that, you get a `windowDeactivated` followed by a `windowClosed` -- or I do, at any rate. The `windowClosing` event is generally for closing a window via an OS control (e.g. the windows red X).
David Moles
(But +1 for some useful test code.)
David Moles
Thanks, David. Totally missed it!
Joseph Gordon
+2  A: 

Closing a window (with dispose()) and hiding it (with setVisible(false)) are different operations, and produce different events -- and closing it from the operating system is yet another different operation that produces yet a different event.

All three will produce windowDeactivated to tell you the window's lost focus, but dispose() will then produce windowClosed, while closing from the OS will first produce windowClosing. If you want to handle both of these the same way, you can set the window to be disposed when closed:

window.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);

In general, setVisible(false) implies that you might want to use the window again, so it doesn't post any window events (apart from windowDeactivated). If you want to detect the hiding of a window, you need to use a ComponentListener;

window.addComponentListener(new ComponentAdapter() {
  @Override
  public void componentHidden() {
    System.out.println("componentHidden()");
  }
})

Note though that this will pretty much only work for explicit setVisible() calls. If you need to detect hiding more generally, you can use a HierarchyListener, but it's probably more trouble than it's worth.

  window.addHierarchyListener(new HierarchyListener() {
    @Override
      public void hierarchyChanged(HierarchyEvent e) {
        System.out.println("valid: " + window.isValid());
        System.out.println("showing: " + window.isShowing());
      }
  });

Note that when you dispose a window you'll get a couple of HierarchyEvents, first for hiding and then for invalidation, but when you hide it with setVisible() it's still valid, so you won't get the invalidation.

David Moles
Thanks David. I was only listening for windowClosing when using dispose. I didn't realize the only the OS closing it produced window closing.
Jeff Storey
I had to find out the hard way myself. :)
David Moles
Ok, I may still not understand the question. But the OP say he wants the "winder listeners to still be notified. My suggestion is to NOT use the dispose method, but to sent a windowClosing event tot the window. This will act just like somebody clicked on the "X" button. The window will be disposed and the window listener will be nofified. Its 2 lines of code. You seem to understand the problem better than I so maybe you will test my suggestion to see if it makes sense.
camickr
My confusion was that I didn't need it on windowClosing, but rather windowClosed. I wasn't trying to intercept windowClosing events, so by putting it in windowClosed, I can get the event either when the dialog is disposed either by hiding it and calling dispose OR if the user clicks the X.
Jeff Storey
camickr, posting a `windowClosing` event gets you a `windowClosing` event and (assuming the default close operation isn't `EXIT_ON_CLOSE`) a `windowDeactivated` event -- as you say, just as if the user clicked the X. That doesn't seem obviously more useful than the events you get with `dispose()` -- if all you want to do is close the window and get some events. It does have the advantage that it matches the behavior of the X, so you can handle both the X and your programmatic closing in the same way, but you can also get that (reversed) with `DISPOSE_ON_CLOSE`. IMHO that's cleaner, but YMMV.
David Moles