Подтвердить что ты не робот

Обнаружение, если компонент 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?

4b9b3361

Ответ 1

Для прослушивания таких событий, происходящих в иерархии, вы можете сделать следующее.

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

Спасибо aioobe за ваш ответ - я попал сюда через 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());
    }
}

Ответ 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().