2012-08-06 5 views
9

Ich brauche Hilfe, um die Ereignisausbreitung in Swing zu verstehen. Ich weiß, dass jedes Ereignis nur von einer Komponente gehandhabt wird. Wenn ich also ein Panel outside mit einem untergeordneten Panel inside habe und ich mouseListeners zu beiden hinzufüge, wird das von inside aufgerufen. Das ist nett und das ist das erwartete Verhalten.MouseMotionListener in untergeordneten Komponente deaktiviert MouseListener in übergeordnete Komponente

Aber ich verstehe das Verhalten in der folgenden Situation nicht: inside registriert einen MouseMotionListener und outside registriert einen MouseListener. Ich erwarte inside, um alle MouseMotionEvents und outside zu empfangen, um die MouseEvents zu empfangen, da für normale MouseEvents auf inside kein Listener ist. Aber das ist nicht der Fall, inside verbraucht irgendwie alle MouseEvents und nicht nur die MouseMotionEvents.

Der folgende Code zeigt das Problem:

import java.awt.*; 
import java.awt.event.*; 
import javax.swing.*; 

public class EventTest { 
public static void main(String... args) { 
    SwingUtilities.invokeLater(new Runnable(){ 
     @Override 
     public void run() { 
      JComponent inside = new JPanel(); 
      inside.setBackground(Color.red); 
      inside.setPreferredSize(new Dimension(200,200)); 
      MouseMotionListener mm = new MouseMotionListener() { 
       @Override 
       public void mouseDragged(MouseEvent arg0) { 
        System.err.println("dragged");      
       } 
       @Override 
       public void mouseMoved(MouseEvent arg0) { 
        System.err.println("moved"); 
       } 
      }; 
      // next line disables handling of mouse clicked events in outside 
      inside.addMouseMotionListener(mm); 

      JComponent outside = new JPanel(); 
      outside.add(inside); 
      outside.setPreferredSize(new Dimension(300,300)); 
      outside.addMouseListener(new MouseAdapter() { 
       public void mouseClicked(MouseEvent e) { 
        System.err.println("clicked"); 
       } 
      }); 

      JFrame frame = new JFrame(); 
      frame.add(outside); 
      frame.pack(); 
      frame.setVisible(true); 
     } 
    }); 
    } 
} 

ich durch die Registrierung ein Zuhörer auf inside für alle Veranstaltungen der Elternkomponente interessieren könnten und dann rufen dispatch das Problem umgehen, könnte das Ereignis an die zu übermitteln Elternteil.

a) Kann mich jemand auf einige Dokumente verweisen, in denen dieses Verhalten beschrieben wird? Die Javadocs von MouseEvent ließen mich denken, dass meine Erwartungen richtig waren. Also brauche ich eine andere Beschreibung, um es zu verstehen.

b) Gibt es eine bessere Lösung als die oben skizzierte?

Danke, Kathrin

Edit: Es ist noch unklar, warum Schaukel auf diese Weise verhält. Aber wie es aussieht, ist der einzige Weg, um das Zeug zum Laufen zu bringen, die Ereignisse manuell weiterzuleiten, ich werde es tun.

+0

+1 für [sscce] (http://sscce.org/). – trashgod

Antwort

8

a) Von design, Java-Maus-Ereignisse "Blase" nur dann, wenn es keine Maus Listener auf der Kind-Komponente.

b) Sie können Ereignisse an eine andere Komponente weiterleiten, wie gezeigt here und unten.

import java.awt.*; 
import java.awt.event.*; 
import javax.swing.*; 

public class EventTest { 

    public static void main(String... args) { 
     SwingUtilities.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       final JComponent outside = new JPanel(); 
       JComponent inside = new JPanel(); 
       inside.setBackground(Color.red); 
       inside.setPreferredSize(new Dimension(200, 200)); 
       inside.addMouseMotionListener(new MouseAdapter() { 

        @Override 
        public void mouseDragged(MouseEvent e) { 
         System.err.println("dragged"); 
        } 

        @Override 
        public void mouseMoved(MouseEvent e) { 
         System.err.println("moved inside"); 
         outside.dispatchEvent(e); 
        } 
       }); 

       outside.add(inside); 
       outside.setPreferredSize(new Dimension(300, 300)); 
       outside.addMouseMotionListener(new MouseAdapter() { 

        @Override 
        public void mouseMoved(MouseEvent arg0) { 
         System.err.println("moved outside"); 
        } 
       }); 

       JFrame frame = new JFrame(); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.add(outside); 
       frame.pack(); 
       frame.setVisible(true); 
      } 
     }); 
    } 
} 
1

Sehr ähnlich trashgod Antwort - können Sie eine MouseAdapter als Bewegung Hörer verwenden, und überschreiben sie alle Ereignisse zu übermitteln Sie von den Eltern behandelt werden möchten. Dies sollte nur einen minimalen Betrag zu Ihrem Code hinzufügen.

 MouseAdapter mm = new MouseAdapter() { 
      @Override 
      public void mouseDragged(MouseEvent arg0) { 
       System.err.println("dragged");      
      } 
      @Override 
      public void mouseMoved(MouseEvent arg0) { 
       System.err.println("moved"); 
      } 
      @Override 
      public void mouseClicked(MouseEvent e) { 
       outside.dispatchEvent(e); 
      } 
     }; 
     // For forwarding events 
     inside.addMouseListener(mm); 
     // For consuming events you care about 
     inside.addMouseMotionListener(mm); 

Ich konnte auch keine Möglichkeit, um die dispatchEvent(e) Methode finden. Ich denke, du bist mit dieser Route festgefahren.

0

Dieser arbeitete für mich:

Ellipse2D mCircle = new Ellipse2D.Double(x,y,size,size); 

    void PassMouseEvent(MouseEvent e) { 
    getParent().dispatchEvent(e); 
    } 

    public void mousePressed(MouseEvent arg0) { 
    if(mCircle.contains(arg0.getX(), arg0.getY())) { 
     // Do stuff if we click on this object 
    } else { 
     // Pass to the underlying object to deal with the mouse event 
     PassMouseEvent(arg0); 
    } 
    } 
Verwandte Themen