【问题标题】:Detect if Java Swing component has been hidden检测 Java Swing 组件是否被隐藏
【发布时间】:2010-04-28 08:31:03
【问题描述】:

假设我们有以下 Swing 应用程序:

    final JFrame frame = new JFrame();

    final JPanel outer = new JPanel();
    frame.add(outer);

    JComponent inner = new SomeSpecialComponent();
    outer.add(inner);

所以在这个例子中,我们只是在框架中有一个外部面板,在面板中有一个特殊组件。这个特殊的组件在隐藏和显示时必须做一些事情。但问题是 setVisible() 是在外部面板上调用的,而不是在特殊组件上调用的。所以我不能覆盖特殊组件中的 setVisible 方法,也不能在它上面使用组件监听器。我可以在父组件上注册监听器,但是如果外面板也在另一个面板中并且这个外面板被隐藏了怎么办?

有没有比递归地向所有父组件添加组件侦听器以检测 SomeSpecialComponent 中的可见性变化更简单的解决方案?

【问题讨论】:

    标签: java swing


    【解决方案1】:

    感谢 aioobe 的 answer - 我是通过 Google 来到这里的,正在寻找同样的东西。 :-) 值得注意的是,Component.isShowing() 与您的 amIVisible() 执行相同的工作,因此修改后的代码 sn-p(包括检查 HierarchyEvent 的性质)可能是:

    class SomeSpecialComponent extends JComponent implements HierarchyListener {
    
        public void addNotify() {
            super.addNotify();
            addHierarchyListener(this);
        }
    
        public void removeNotify() {
            removeHierarchyListener(this);
            super.removeNotify();
        }
    
        public void hierarchyChanged(HierarchyEvent e) {
            if ((e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) != 0)
                System.out.println("Am I visible? " + isShowing());
        }
    }
    

    【讨论】:

      【解决方案2】:

      要侦听层次结构中发生的此类事件,您可以执行以下操作。

      class SomeSpecialComponent extends JComponent implements HierarchyListener {
      
          private boolean amIVisible() {
              Container c = getParent();
              while (c != null)
                  if (!c.isVisible())
                      return false;
                  else
                      c = c.getParent();
              return true;
          }
      
          public void addNotify() {
              super.addNotify();
              addHierarchyListener(this);
          }
      
          public void removeNotify() {
              removeHierarchyListener(this);
              super.removeNotify();
          }
      
          public void hierarchyChanged(HierarchyEvent e) {
              System.out.println("Am I visible? " + amIVisible());
          }
      
      }
      

      您甚至可以更精确地处理 HierarchyEvents。来看看

      http://java.sun.com/javase/6/docs/api/java/awt/event/HierarchyEvent.html

      【讨论】:

        【解决方案3】:

        看看 ComponentListener(或 ComponentAdapter)

        http://java.sun.com/docs/books/tutorial/uiswing/events/componentlistener.html

        http://docs.oracle.com/javase/8/docs/api/java/awt/event/ComponentListener.html

        特别是方法:

        void componentHidden(ComponentEvent e)
            Invoked when the component has been made invisible.
        

        完整的解决方案如下所示:

        inner.addComponentListener(new ComponentAdapter() {
            public void componentHidden(ComponentEvent ce) {
                System.out.println("Component hidden!");
            }
        });
        

        如果隐藏时应该执行的操作与 SomeSpecialCompnent 紧密耦合,我建议让 SomeSpecialComponent 实现 ComponentListener,并在其构造函数中添加自己作为 ComponentEvents 的侦听器。

        另一种有用的方法(与添加/删除操作更相关,可能不适合您的特定场景)是覆盖addNotify()removeNotify()

        【讨论】:

        • 父组件隐藏时不触发该事件,仅在调用特殊组件本身的setVisible()方法时触发。正如我所说,我正在寻找一种更简单的解决方案,然后递归地附加到所有父组件的 componentListener 事件。
        猜你喜欢
        • 2014-08-21
        • 2012-05-24
        • 1970-01-01
        • 1970-01-01
        • 2011-08-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多