javaswingancestorcomponentlistener

Is there a way to get notification when JComponent is not visible anymore beucase parent is removed from collection?


Say I have a simple JFrame with a JTabbedPane containing 3 panels, and the second panel contains a JComponent. Is there a way the JComponent to be notified when "Tab 2" panel is removed from its container? My problem is that the JComponent may be deep in the hierarchy.

Obviously, I am looking for SWING solution here... :)

 ,'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''`.
 |                                                                |
 | ,----------Y.......................                            |
 | | Tab 1    | Tab 2     | Tab 3    |                            |
 | :..........:           :.....................................  |
 | |                                                           |  |
 | |                                                           |  |
 | |                                                           |  |
 | |               +--------------------+                      |  |
 | |               |Some JComponent here|                      |  |
 | |               +--------------------+                      |  |
 | |                                                           |  |
 | |                                                           |  |
 | |                                                           |  |
 | |                                                           |  |
 | |                                                           |  |
 | |                                                           |  |
 | |                                                           |  |
 | |                                                           |  |
 | |                                                           |  |
 | |                                                           |  |
 | `-----------------------------------------------------------'  |
 `-----------------------------------------------------------------

I tried to do this with the ancestorRemoved(), but no luck... I am obviously doing something wrong...

PS. the ASCII art is made with JavE.


Solution

  • I'd be use ComponentListener for this job (CardLayout is so close, similar in compare with JTabbedPane), code example contains all related listeners (disclaimer --> notice blocking EDT works only as code example and in this form only)

    Ancesor & HierarchyListener are little bit asynchronous, maybe there is your problem to catch proper event from AncestorListener

    my question about similar issue

    import java.awt.BorderLayout;
    import java.awt.CardLayout;
    import java.awt.event.ComponentEvent;
    import java.awt.event.ComponentListener;
    import java.awt.event.HierarchyEvent;
    import java.awt.event.HierarchyListener;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.event.AncestorEvent;
    import javax.swing.event.AncestorListener;
    
    public class CardlayoutTest extends JFrame {
    
        private static final long serialVersionUID = 1L;
        public CardLayout card = new CardLayout();
    
        public CardlayoutTest() {
            JPanel pnlA = new JPanel(new BorderLayout());
            pnlA.add(new JButton("A"), BorderLayout.CENTER);
            JPanel pnlB = new JPanel(new BorderLayout());
            pnlB.add(new JButton("B"), BorderLayout.CENTER);
            JPanel pnlC = new JPanel(new BorderLayout());
            pnlC.add(new JButton("C"), BorderLayout.CENTER);
    
            setDefaultCloseOperation(EXIT_ON_CLOSE);
            setLayout(card);
            add(pnlA, "A");
            add(pnlB, "B");
            add(pnlC, "C");
    
            pnlA.addAncestorListener(new EventHandler());
            pnlB.addAncestorListener(new EventHandler());
            pnlC.addAncestorListener(new EventHandler());
    
            pnlA.addHierarchyListener(new EventHandler());
            pnlB.addHierarchyListener(new EventHandler());
            pnlB.addHierarchyListener(new EventHandler());
    
            pnlA.addComponentListener(new EventHandler());
            pnlB.addComponentListener(new EventHandler());
            pnlB.addComponentListener(new EventHandler());
        }
    
        class EventHandler implements AncestorListener, ComponentListener, HierarchyListener {
    
            @Override
            public void ancestorAdded(AncestorEvent event) {
                System.out.println("CardlayoutTest.EventHandler.ancestorAdded()");
            }
    
            @Override
            public void ancestorMoved(AncestorEvent event) {
                System.out.println("CardlayoutTest.EventHandler.ancestorMoved()");
            }
    
            @Override
            public void ancestorRemoved(AncestorEvent event) {
                System.out.println("CardlayoutTest.EventHandler.ancestorRemoved()");
            }
    
            @Override
            public void hierarchyChanged(HierarchyEvent e) {
                System.out.println("Components Change: " + e.getChanged());
                if ((e.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED) != 0) {
                    if (e.getComponent().isDisplayable()) {
                        System.out.println("Components DISPLAYABILITY_CHANGED : " + e.getChanged());
                    } else {
                        System.out.println("Components DISPLAYABILITY_CHANGED : " + e.getChanged());
                    }
                }
                if ((e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) != 0) {
                    if (e.getComponent().isDisplayable()) {
                        System.out.println("Components SHOWING_CHANGED : " + e.getChanged());
                    } else {
                        System.out.println("Components SHOWING_CHANGED : " + e.getChanged());
                    }
                }
            }
    
            public void componentHidden(ComponentEvent e) {
                System.out.println(e.getComponent().getClass().getName() + " --- Hidden");
            }
    
            public void componentMoved(ComponentEvent e) {
                System.out.println(e.getComponent().getClass().getName() + " --- Moved");
            }
    
            public void componentResized(ComponentEvent e) {
                System.out.println(e.getComponent().getClass().getName() + " --- Resized ");
            }
    
            public void componentShown(ComponentEvent e) {
                System.out.println(e.getComponent().getClass().getName() + " --- Shown");
            }
        }
    
        public static void main(String[] args) {
            CardlayoutTest t = new CardlayoutTest();
            t.setSize(500, 500);
            System.out.println("CardlayoutTest.main()------------------------ FIRST");
            t.card.show(t.getContentPane(), "A");
            t.setVisible(true);
            System.out.print("\n");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
            }
            System.out.println("CardlayoutTest.main()------------------------ SECOND");
            t.card.show(t.getContentPane(), "B");
            System.out.print("\n");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
            }
            System.out.println("CardlayoutTest.main()------------------------ THIRD");
            t.card.show(t.getContentPane(), "C");
            System.out.print("\n");
        }
    }