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