2010-09-29 5 views
8

Je souhaite créer une application dans laquelle certains événements sont censés être traités comme s'ils étaient livrés dans des conteneurs parents. Par exemple, j'ai un JPanel qui contient JLabel. Le top JPanel implémente mousepress et glisser en ce moment. Que dois-je faire pour que les événements semblent être arrivés à JPanel au lieu de l'étiquette elle-même? (il est important de changer l'objet source)Transmission d'événements au parent

Existe-t-il une meilleure solution que d'implémenter réellement les événements et de les répliquer dans le parent? (Cela deviendrait fastidieux après certains objets avec> 5 enfants).

+0

Pourquoi avez-vous besoin de le faire (par exemple)? – Pete

+0

J'ai des objets avec beaucoup d'étiquettes, qui devraient être déplaçables partout où ils ont été cliqués la première fois. Pour le moment, ils ne peuvent être déplacés que lorsque je clique sur l'arrière-plan de l'élément, et non sur une étiquette à l'intérieur. – viraptor

Répondre

10

Lors de l'écoute de l'événement, vous pouvez envoyer l'événement au composant parent.

Étant myEvent l'argument de la fonction de gestion des événements:

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

Mais cette solution implique la création d'une nouvelle EventListener pour chaque élément à ajouter.

Ainsi, vous pouvez créer un seul gestionnaire d'événement et de le réutiliser, en ajoutant à tous les enfants, comme choisis ceci:

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

Cela a créé un débordement de pile dans le thread awt (lorsque le parent renvoyait l'événement au contrôle enfant). Des idées sur la façon de contourner ce problème? Je ne peux pas éditer la classe parente, mais j'en ai besoin pour obtenir l'événement mais empêcher d'agir sur l'événement que le parent me rendra à mon contrôle. – ed22

+0

Ressources-sage c'est une mauvaise idée. Vous ajoutez beaucoup de frais généraux pour rien. Il est beaucoup plus efficace de supprimer les écouteurs de la souris sur les éléments enfants. Vous pouvez voir ma réponse pour la façon de le faire récursivement. – qwertzguy

2

Vous devez convertir événement avant de l'envoyer au parent. La conversion inclut la conversion des coordonnées vers parent-parent.

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

Votre réponse est en fait un commentaire à la réponse de Tomas Narros. – SeniorJD

+0

@SeniorJD Ceci est une réponse parfaitement valide. Il s'appuie simplement sur l'autre réponse et peut se suffire à lui-même. Il serait préférable que Wojtek décrive un peu plus pourquoi cet ajustement est nécessaire. –

+0

Du point de vue des ressources, c'est une mauvaise idée. Vous ajoutez beaucoup de frais généraux pour rien. Il est beaucoup plus efficace de supprimer les écouteurs de la souris sur les éléments enfants. Vous pouvez voir ma réponse pour la façon de le faire récursivement. – qwertzguy

-1

événements de souris sont ciblées vers le plus profond composant qui a auditeurs de souris. De ce fait, pour atteindre votre objectif, vous pouvez simplement supprimer tous les écouteurs de la souris sur le JLabel et il ne sera jamais choisi comme cible pour les événements de la souris.

Le code suivant désactive les auditeurs de la souris sur les composants donnés et leurs enfants récursive:

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

Personne qui a -1 ans: est-ce que vous voulez expliquer pourquoi? Faire cela de cette façon est bien meilleur pour la ressource que d'ajouter un écouteur qui envoie au parent. – qwertzguy