2012-06-18 2 views
5

Ich habe eine Swing-Komponente, die mehrere Unterkomponenten hat. Was ich tun möchte, ändern Sie eine Beschriftung, wenn die Maus über einer dieser Komponenten ist, und ändern Sie es dann in etwas anderes, wenn die Maus von allen Komponenten bewegt wird. Ich versuche, einen effizienteren Weg zu finden, dies zu tun.Swing Mouse Listeners von Kind Komponenten abgefangen werden

Zur Zeit habe ich Maus Zuhörer über alle untergeordneten Komponenten, wie etwas aussehen:

class AMouseListener extends MouseAdapter { 
    private boolean mouseOver; 
    mouseEntered(MouseEvent e) { mouseOver = true; updateLabel(); } 
    mouseExited(MouseEvent e) { mouseOver = false; updateLabel(); } 

    void updateLabel() { 
     String text = "not-over-any-components"; 
     // listeners are each of the listeners added to the child components 
     for (AMouseListener listener :listeners) { 
      if (listener.mouseOver) { 
      text = "over-a-component"; 
      break; 
      } 
     } 
    } 
} 

Dies funktioniert, aber ich fühle mich wie sollte es ein besserer Weg, dies zu umgehen, indem nur mouseEntered und mouseExited Behandlung von Ereignissen auf dem übergeordneten Container, aber da die untergeordneten Komponenten diese Ereignisse abfangen, bin ich mir nicht sicher, wie ich das machen soll (ich habe nicht unbedingt die Kontrolle über die untergeordneten Komponenten, daher kann ich die Mausereignisse nicht zum übergeordneten Ereignis weiterleiten Wenn ich wollte).

+0

Warum alle erforderlichen Komponenten nicht zuordnen den gleichen Hörer. Auf diese Weise lösen alle genau die gleiche Aktion aus. – Morfic

+0

könnten Sie vielleicht Ihren Code erweitern, um das Problem zu zeigen? Da ich das Problem und Ihre "gewollte" Lösung –

+0

@Grove nicht ganz verstehe, gibt es, wenn ich jeder Komponente denselben Listener zuweiße, ein potentielles Rennen, abhängig davon, ob mouseEntered für eine Komponente vor oder nach mouseExited für eine andere auftritt. Nehmen wir an, ich bin über Komponente1 und ich bewege die Maus nach Komponente2. Wenn die mouseEntered Component2 vor mouseExited Component1 verarbeitet wird, ist der Text falsch. Ich bin mir nicht sicher, ob es eine garantierte Reihenfolge für diese Ereignisse gibt, da die gleiche Mausbewegung die ausgehende Komponente1 und die Eingabe von Komponente2 erzeugen würde. –

Antwort

7

Zum Beispiel

enter image description here

enter image description here

import java.awt.Component; 
import java.awt.Dimension; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import javax.swing.*; 

public class TestMouseListener { 

    public static void main(String[] args) { 
     final JComboBox combo = new JComboBox(); 
     combo.setEditable(true); 
     for (int i = 0; i < 10; i++) { 
      combo.addItem(i); 
     } 
     final JLabel tip = new JLabel(); 
     tip.setPreferredSize(new Dimension(300, 20)); 
     JPanel panel = new JPanel(); 
     panel.add(combo); 
     panel.add(tip); 
     JFrame frame = new JFrame(); 
     frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
     frame.add(panel); 
     frame.pack(); 
     frame.setVisible(true); 
     panel.addMouseListener(new MouseAdapter() { 

      @Override 
      public void mouseEntered(MouseEvent e) { 
       tip.setText("Outside combobox"); 
      } 

      @Override 
      public void mouseExited(MouseEvent e) { 
       Component c = SwingUtilities.getDeepestComponentAt(
        e.getComponent(), e.getX(), e.getY()); 
       // doesn't work if you move your mouse into the combobox popup 
       tip.setText(c != null && SwingUtilities.isDescendingFrom(
        c, combo) ? "Inside combo box" : "Outside combobox"); 
      } 
     }); 
    } 

    private TestMouseListener() { 
    } 
} 
2

Schauen Sie sich die Dokumentation und Beispiele für die "Glasscheibe" an.
Dies sollte Ihnen geben, was Sie brauchen: The Glass Pane

+0

Ich könnte die Glasscheibe für den gesamten Rahmen verwenden, aber die Elternkomponente ist nur ein JPanel, der keine Glasscheibe hat. Ich habe versucht, die Lösung nur auf diese Elternkomponente zu beschränken, damit sie in anderen Teilen der App wiederverwendet werden kann (in denen sich eine Glasscheibe befinden kann oder auch nicht). –

+0

Nicht sicher, es gibt viel Alternative. Ich würde eine Support-Klasse erstellen, um eine Glasscheibe zu installieren und mit ihr zu interagieren. Das Panel kann dann diese Support-Klasse instanziieren und mit ihr interagieren, wodurch ein Glasfenster im übergeordneten JFrame installiert wird, um Ereignisse für die Grenzen Ihres Bereichs innerhalb dieses Rahmens zu erfassen. Dann könnten die Ereignisse an einen Maus-Listener weitergeleitet werden, der vom Panel nominiert wurde. Also würde die ganze harte Arbeit von der Support-Klasse erledigt werden und das Panel würde nur die Ereignisse bekommen, die es benötigt. – davidfrancis

+0

@Jeff Storey [vielleicht überhaupt nicht wahr] (http: // stackoverflow.com/a/9734016/714968) – mKorbel

1

Sie könnten eine einzelne Instanz des Listeners initiieren und diese Instanz jeder Komponente hinzufügen. So:

AMouseListener aMouseListener=new AMouseListener(); 

for each(Component c:components) { 
caddMouseListener(aMouseListener); 
} 
+0

David, ja, das könnte ich machen. Meine Sorge war mit der Bestellung von Ereignissen. Wenn das mouseExited/mouseEntered-Verhalten garantiert werden kann, ist dies ein einfaches Problem. –

+0

Haben Sie es getestet? Ich weiß, es ist offensichtlich, aber probier es aus, gehe über die Komponenten und schau, was es produziert. –

+0

Sicher, aber selbst wenn es funktioniert, bin ich nicht sicher, was (wenn überhaupt) Garantien über die Bestellung gemacht werden. –

Verwandte Themen