检测是否已隐藏Java Swing组件

时间:2010-04-28 08:31:03

标签: java swing

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

    final JFrame frame = new JFrame();

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

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

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

是否有一个比向所有父组件递归添加组件侦听器以检测SomeSpecialComponent中的可见性更改更简单的解决方案?

3 个答案:

答案 0 :(得分:23)

感谢aioobe为你的answer - 我通过Google来到这里,寻找同样的事情。 :-)值得注意的是,Component.isShowing()amIVisible()的工作相同,因此修改后的代码段(包括对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());
    }
}

答案 1 :(得分:13)

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

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

答案 2 :(得分: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()