Difficulty in using addWindowListener

715 Views Asked by At

I am trying to implement a listener to detect the closing of a window. My main class is extending other classes so I am unable to extend JFrame which is not allowing me to use addWindowListener.

I have tried the code below but it is not working.

public class PowerPanel extends AnotherPanel  implements ActionListener, PropertyChangeListener {
    // logic …
        this.addWindowListener(new WindowAdapter() {
            public void windowClosing (WindowEvent e ) {
        // do things
    }
});
}

The error I am getting is indicating that addWindowListener is "undefined for the type PowerPanel."

1

There are 1 best solutions below

0
Mikle Garin On

You can't add window listener to your panel - you need to add it into the java.awt.Window instance which in your case is a JFrame.

If it is hard for you to pass your JFrame instance into the panel - you can access it in a different way:

public class SamplePanel extends JPanel
{
    /**
     * Simple panel example that has no idea about it's parent window.
     */
    public SamplePanel ()
    {
        super ();

        // Your custom window listener
        final WindowAdapter windowAdapter = new WindowAdapter ()
        {
            @Override
            public void windowClosing ( final WindowEvent e )
            {
                System.out.println ( "Window is closing" );
            }
        };

        // Ancestor availability listener
        // It will make sure that whenever component appears on some visible window 
        // and is displayable container - we will add our window listener to it
        addAncestorListener ( new AncestorAdapter ()
        {
            /**
             * Saved window to remove listener from later on.
             */
            private Window window = null;

            @Override
            public void ancestorAdded ( final AncestorEvent event )
            {
                // Component appeared on some window, we can add our listener now
                addListener ();
            }

            @Override
            public void ancestorMoved ( final AncestorEvent event )
            {
                // Re-adding listener to potentially new parent window
                removeListener ();
                addListener ();
            }

            @Override
            public void ancestorRemoved ( final AncestorEvent event )
            {
                // Component was hidden or removed, we need to remove our listener
                removeListener ();
            }

            /**
             * Adds window listener.
             */
            protected void addListener ()
            {
                window = SwingUtilities.getWindowAncestor ( SamplePanel.this );
                if ( window != null )
                {
                    window.addWindowListener ( windowAdapter );
                }
            }

            /**
             * Removes window listener.
             */
            protected void removeListener ()
            {
                if ( window != null )
                {
                    window.removeWindowListener ( windowAdapter );
                    window = null;
                }
            }
        } );
    }

    /**
     * Sample main method for runing the example.
     *
     * @param args arguments
     */
    public static void main ( final String[] args )
    {
        SwingUtilities.invokeLater ( new Runnable ()
        {
            @Override
            public void run ()
            {
                final JFrame frame = new JFrame ();

                final SamplePanel panel = new SamplePanel ();
                panel.add ( new JLabel ( "Sample panel content" ) );
                frame.add ( panel );

                frame.pack ();
                frame.setDefaultCloseOperation ( JFrame.DISPOSE_ON_CLOSE );
                frame.setLocationRelativeTo ( null );
                frame.setVisible ( true );
            }
        } );
    }
}

With this code your panel will automatically register window listener on it's parent window whenever it is displayed. It will also automatically remove the listener once panel is hidden or removed from the window, so potentially this is the best solution you can have.

Be careful though, if you will use that panel multiple times on the same window - all of the instances will add their own listener and will all perform on-close action separately. If you want to perform your on-close operation just once per window/frame/dialog instance - you need to add the listener on the window itself, preferably where it is created not to make it obscure.

You might also notice that in my example there is actually a method that retrieves panel's parent window directly:

window = SwingUtilities.getWindowAncestor ( SamplePanel.this );

Although you can't use it in your panel directly, because at the moment when panel is created it is not yet added into any container, let alone visible window. That is why the solution with ancestor listener that i've shown is required.