2010-09-29 9 views
8

Me gustaría crear una aplicación donde se supone que algunos eventos se manejarán como si se entregaran en contenedores principales. Por ejemplo, tengo un JPanel que contiene JLabel. El JPanel superior implementa mousepress y arrastrando en este momento. Qué debo hacer para que los eventos parezcan que llegaron a JPanel en lugar de a la etiqueta en sí. (Cambiar el objeto de origen es importante)Pasar eventos al padre

¿Hay alguna solución mejor que implementar realmente los eventos y replicarlos en el elemento primario? (Esto sería tedioso después de algunos objetos con> 5 niños).

+0

¿Por qué necesita para hacer esto (ejemplo)? – Pete

+0

Tengo objetos con muchas etiquetas, que deberían poder arrastrarse en cualquier lugar en el que se hayan hecho clic la primera vez. En este momento solo se pueden arrastrar cuando hago clic en el fondo del elemento, no en ninguna etiqueta dentro. – viraptor

Respuesta

10

En su detector de eventos, puede enviar el evento al componente primario.

Ser myEvent el manejo argumento de la función de eventos:

Component source=(Component)myEvent.getSource(); 
source.getParent().dispatchEvent(myEvent); 

Pero esta solución implica la creación de un nuevo EventListener para cada elemento a añadir.

Por lo tanto, se podría crear un único controlador de eventos y reutilizarla, añadiéndolo a todos los hijos escogidos, así:

final Container parent=this; //we are a the parent container creation code 
MouseListener myCommonListener=new MouseListener() { 
    @Override 
    public void mouseClicked(MouseEvent e) { 
     parent.dispatchEvent(e); 
    } 
    @Override 
    public void mouseEntered(MouseEvent e) { 
     parent.dispatchEvent(e); 
    } 
    @Override 
    public void mouseExited(MouseEvent e) { 
     parent.dispatchEvent(e); 
    } 
    @Override 
    public void mousePressed(MouseEvent e) { 
     parent.dispatchEvent(e); 
    } 
    @Override 
    public void mouseReleased(MouseEvent e) { 
     parent.dispatchEvent(e); 
    } 
}; 

JLabel label=new JLabel("This is the first Label"); 
label.addMouseListener(myCommonListener); 

JLabel label2=new JLabel("This is the second Label"); 
label2.addMouseListener(myCommonListener); 
//... and so on 
+0

Esto creó un desbordamiento de pila en el subproceso awt (ya que el padre pasaba el evento al control secundario). ¿Alguna idea sobre cómo solucionar este problema? No puedo editar la clase principal, sin embargo, necesito obtener el evento pero evitar actuar en caso de que el padre vuelva a mi control. – ed22

+0

Recurso sabio esto es una mala idea. Estás agregando muchos gastos indirectos por nada. Es mucho más eficiente eliminar los oyentes del mouse en los elementos secundarios. Puedes ver mi respuesta sobre cómo hacerlo recursivamente. – qwertzguy

2

Debe convertir evento antes de despacharlo a los padres. La conversión incluye la traducción de coordenadas al pariente-pariente.

public class RedispatchingMouseAdapter implements MouseListener, MouseWheelListener, MouseMotionListener{ 

    public void mouseClicked(MouseEvent e) { 
     redispatchToParent(e); 
    } 

    public void mousePressed(MouseEvent e) { 
     redispatchToParent(e); 
    } 

    public void mouseReleased(MouseEvent e) { 
     redispatchToParent(e); 
    } 

    public void mouseEntered(MouseEvent e) { 
     redispatchToParent(e); 
    } 

    public void mouseExited(MouseEvent e) { 
     redispatchToParent(e); 
    } 

    public void mouseWheelMoved(MouseWheelEvent e){ 
     redispatchToParent(e); 
    } 

    public void mouseDragged(MouseEvent e){ 
     redispatchToParent(e); 
    } 

    public void mouseMoved(MouseEvent e) { 
     redispatchToParent(e); 
    } 

    private void redispatchToParent(MouseEvent e){ 
     Component source = (Component) e.getSource(); 
     MouseEvent parentEvent = SwingUtilities.convertMouseEvent(source, e, source.getParent()); 
     source.getParent().dispatchEvent(parentEvent); 
    } 
} 
+0

Tu respuesta es realmente un comentario a la respuesta de Tomas Narros. – SeniorJD

+0

@SeniorJD Esta es una respuesta perfectamente válida. Simplemente se basa en la otra respuesta y puede sostenerse por sí mismo. Sería mejor si Wojtek describiera un poco más por qué es necesario este ajuste. –

+0

Recurso sabio esto es una mala idea. Estás agregando muchos gastos indirectos por nada. Es mucho más eficiente eliminar los oyentes del mouse en los elementos secundarios. Puedes ver mi respuesta sobre cómo hacerlo recursivamente. – qwertzguy

-1

Los eventos de ratón se orientan de forma automática el componente más profundo que tiene oyentes ratón.

Debido a esto, para lograr su objetivo, simplemente puede eliminar todos los detectores de mouse en el JLabel y nunca se elegirá como el objetivo para los eventos del mouse.

El siguiente código desactivará oyentes ratón sobre los componentes indicados y sus hijos de forma recursiva:

private void disableMouseForComponent(Component... components) { 
    for (Component c : components) { 
     if (c instanceof Container) { 
      disableMouseForComponent(((Container) c).getComponents()); 
     } 
     for (MouseListener l : c.getMouseListeners()) { 
      c.removeMouseListener(l); 
     } 
     for (MouseMotionListener l : c.getMouseMotionListeners()) { 
      c.removeMouseMotionListener(l); 
     } 
    } 
} 
+0

Persona que ha hecho -1: ¿te importa explicar por qué? Hacerlo de esta manera es mucho mejor en términos de recursos que agregar un oyente que despache al padre. – qwertzguy

Cuestiones relacionadas