【问题标题】:Swing AncestorListener: Don't fire for tab switching?Swing AncestorListener:不要触发标签切换?
【发布时间】:2013-03-21 15:54:11
【问题描述】:

我正在使用以下代码让我的组件在添加/删除时分别注册/取消注册事件侦听器。

addAncestorListener(new AncestorListener() {
        @Override public void ancestorRemoved(AncestorEvent event) {
            log.info("========= Remove listeners by " + ContentViewingComponent.this);
            ...
        }
        @Override public void ancestorMoved(AncestorEvent event) {}
        @Override public void ancestorAdded(AncestorEvent event) {
            log.info("========= Add listeners by " + ContentViewingComponent.this);
            ...
        }
    });

我的意图是在大多数情况下,这两个事件(添加和删除)基本上都会触发一次,即创建和添加组件时以及删除和忘记组件时。

但是,事实证明,当该组件所在的选项卡(JTabbedPane)被选中/隐藏时,它们也会被触发。有没有办法规避/检测到这一点?

可能是JTabbedPane 的一个版本,它使用显示/隐藏而不是添加/删除? 更新:更多调查表明该组件实际上并未被删除,而是选项卡被隐藏,ancestorRemoved()也为此着火。我可以检测组件是否仍然具有 root* 并忽略该事件(如果有),但问题是当组件实际被移除(不可见时)时它不会再次触发。

*嗯,这还有待观察。似乎ancestorRemoved() 在实际删除之前触发,所以我无法沿着getParent() 链查找组件是否有根。 更新:通过稍后使用SwingUtilities.invokeLater() 检查它来修复。


(对于那些熟悉 Flash/AS3 的人,我正在寻找与 ADDED_TO_STAGE/REMOVED_FROM_STAGE 事件等效的 Swing。)

【问题讨论】:

  • Swing 监听器在触发时会触发。但是,您可以在侦听器中使用 if 语句仅针对您想要的事件执行代码。
  • @GilbertLeBlanc 是的,但是有一个问题。我可以忽略一个仅表示“不可见”的事件,但如果该组件随后被移除(不可见),它不会让我知道。

标签: java swing jtabbedpane ancestor


【解决方案1】:

已通过使用 HierarchyListener 修复。

public static void addDisplayableListeners(final Component comp, final Runnable onDisplayable, final Runnable onNotDisplayable) {
    comp.addHierarchyListener(new HierarchyListener() {
        @Override public void hierarchyChanged(HierarchyEvent e) {
            System.out.println("HIERARCHY CHANGE ===== " + comp);
            final boolean dc = (e.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED) != 0;
            if (dc) {
                System.out.println("DISPLAYABILITY_CHANGED");
                if (comp.isDisplayable()) {
                    onDisplayable.run();
                } else {
                    onNotDisplayable.run();
                }
            }
        }
    });
}

旧版本:

    addHierarchyListener(new HierarchyListener() {

        private boolean hadRoot = false;

        @Override public void hierarchyChanged(HierarchyEvent e) {

            System.out.println("HIERARCHY CHANGE ===== " + ContentViewingComponent.this);

            final boolean hasRoot = Swing.hasRoot(ContentViewingComponent.this);
            System.out.println("Has root: " + hasRoot);

            if (hasRoot != hadRoot) {

                System.out.println("...which is not what was.");
                hadRoot = hasRoot;

                if (hasRoot) {
                    log.info("========= Add listeners by " + ContentViewingComponent.this);
                    ...
                } else {
                    log.info("========= Remove listeners by " + ContentViewingComponent.this);
                    ...
                }
            }

        }
    });

注意:我会看看我是否可以用@mKorbel 的答案中提到的官方方法替换我自己的助手(hadRoothasRoot())。

【讨论】:

    【解决方案2】:

    我的意图是这两个事件(添加和删除)基本上都会触发 在大多数情况下一次,即在创建和添加组件时 以及当它被删除和遗忘时

    有 AncestorListener、ComponentListener 和 HierarchyListener,它们可以是异步的,与使用 SwingUtilities 从这些事件或祖先获取组件的方式相同

    例如

    import java.awt.BorderLayout;
    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.event.ComponentEvent;
    import java.awt.event.ComponentListener;
    import java.awt.event.HierarchyEvent;
    import java.awt.event.HierarchyListener;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JTabbedPane;
    import javax.swing.event.AncestorEvent;
    import javax.swing.event.AncestorListener;
    
    public class MyTabbedPane {
    
        private JTabbedPane tabbedPane = new JTabbedPane();
        private JFrame f = new JFrame();
        private JLabel label1 = new JLabel("Tab1");
        private JLabel label2 = new JLabel("Tab2");
        private JLabel label3 = new JLabel("Tab3");
        private JLabel label4 = new JLabel("Tab4");
    
        public MyTabbedPane() {
            tabbedPane.addTab("Tab1", label1);
            tabbedPane.addTab("Tab2", label2);
            tabbedPane.addTab("Tab3", label3);
            tabbedPane.addTab("Tab4", label4);
            tabbedPane.setTabPlacement(JTabbedPane.TOP);
            tabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
    
            label1.addAncestorListener(new EventHandler());
            label2.addAncestorListener(new EventHandler());
            label3.addAncestorListener(new EventHandler());
            label4.addAncestorListener(new EventHandler());
    
            label1.addHierarchyListener(new EventHandler());
            label2.addHierarchyListener(new EventHandler());
            label3.addHierarchyListener(new EventHandler());
            label4.addAncestorListener(new EventHandler());
    
            label1.addComponentListener(new EventHandler());
            label2.addComponentListener(new EventHandler());
            label3.addComponentListener(new EventHandler());
            label4.addComponentListener(new EventHandler());
    
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.add(tabbedPane, BorderLayout.CENTER);
            f.setPreferredSize(new Dimension(600, 400));
            f.pack();
            f.setVisible(true);
        }
    
        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());
                    }
                }
            }
    
            @Override
            public void componentHidden(ComponentEvent e) {
                System.out.println(e.getComponent().getClass().getName() + " --- Hidden");
            }
    
            @Override
            public void componentMoved(ComponentEvent e) {
                System.out.println(e.getComponent().getClass().getName() + " --- Moved");
            }
    
            @Override
            public void componentResized(ComponentEvent e) {
                System.out.println(e.getComponent().getClass().getName() + " --- Resized ");
            }
    
            @Override
            public void componentShown(ComponentEvent e) {
                System.out.println(e.getComponent().getClass().getName() + " --- Shown");
            }
        }
    
        public static void main(String args[]) {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    MyTabbedPane frame = new MyTabbedPane();
    
                }
            });
        }
    }
    

    【讨论】:

    • 与此同时,我“修复”了它(请参阅我自己的答案),但我也可能会从这个答案中加入一些元素。
    猜你喜欢
    • 2023-04-02
    • 2016-08-11
    • 2021-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多