2010-04-28 12 views
19

Supongamos que tenemos la siguiente aplicación Swing:detectar si componente Swing de Java se ha ocultado

final JFrame frame = new JFrame(); 

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

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

Así que en este ejemplo simplemente tenemos un panel exterior en el marco y un componente especial en el panel. Este componente especial debe hacer algo cuando está oculto y se muestra. Pero el problema es que se llama a setVisible() en el panel exterior y no en el componente especial. Por lo tanto, no puedo anular el método setVisible en el componente especial y tampoco puedo usar un componente listener en él. Podría registrar el oyente en el componente principal, pero ¿qué ocurre si el panel exterior también está en otro panel y este panel exterior externo está oculto?

¿Existe una solución más fácil que la adición recursiva de detectores de componentes a todos los componentes principales para detectar un cambio de visibilidad en SomeSpecialComponent?

Respuesta

13

Para escuchar este tipo de eventos que ocurren en la jerarquía, puede hacer lo siguiente.

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()); 
    } 

} 

Incluso podría ser más preciso en el tratamiento de HierarchyEvents. Echar un vistazo a

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

3

Tener un vistazo a la ComponentListener (o 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

Y específicamente el método:

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

Una solución completa sería algo como:

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

Si las acciones que se deben llevar a cabo al ocultar están estrechamente relacionadas con SomeSpecialCompnent, sugeriría que SomeSpecialComponent implemente ComponentListener y se agregue como listener para ComponentEvents en su constructor.

Otra forma útil (más relacionada con las operaciones de agregar/eliminar y tal vez no adecuada para su situación específica) es anular addNotify() y removeNotify().

+3

Este evento no se desencadena cuando el padre El componente está oculto, solo se activa cuando se llama al método setVisible() del componente especial en sí. Como dije, estoy buscando una solución que sea FÁCIL y que luego se adjunte recursivamente a los eventos componentListener de todos los componentes principales. – kayahr

+0

Veo el problema ahora :-) viene una nueva respuesta ... – aioobe

22

Gracias aioobe para su answer - Tengo aquí a través de Google, en busca de lo mismo. :-) Vale la pena señalar que Component.isShowing() hace el mismo trabajo que su amIVisible() sin embargo, por lo que un fragmento de código revisado (incluyendo un control sobre la naturaleza de la HierarchyEvent) podría ser:

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()); 
    } 
} 
Cuestiones relacionadas