2012-06-18 7 views
5

Possiedo un componente di rotazione con diversi componenti secondari. Quello che voglio fare cambia qualche etichetta se il mouse si trova su uno di questi componenti, e poi lo cambia in qualcos'altro se il mouse si sposta da tutti i componenti. Sto cercando di trovare un modo più efficiente per farlo.Ascoltatori del mouse oscillante intercettati da componenti secondari

Attualmente ho ascoltatori del mouse su tutte le componenti figlio che sembrano qualcosa di simile:

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

Questo funziona, ma mi sento come ci dovrebbe essere un modo migliore per gestire questa situazione da solo la gestione degli eventi mouseEntered e mouseExited sul contenitore padre, ma poiché i componenti figlio intercettano questi eventi, non sono sicuro su come procedere (non ho necessariamente il controllo sui componenti figlio, quindi non posso inoltrare gli eventi del mouse all'evento padre se volessi).

+0

Perché non assegnare lo stesso ascoltatore a tutti i componenti necessari. In questo modo, tutti attivano esattamente la stessa azione. – Morfic

+0

potresti espandere il tuo codice per mostrare il problema? poiché non capisco perfettamente il problema e la soluzione "ricercata" –

+0

@Grove, se assegno lo stesso listener a ciascun componente, esiste una potenziale competizione a seconda che mouseEntered su un componente si verifichi prima o dopo il mouse Esegui su un altro. Diciamo che sono sopra component1 e sposto il mouse verso component2. Se il mouseEntered Component2 viene elaborato prima di mouseExited Component1, il testo sarà errato. Non sono sicuro se ci sia un ordine garantito per questi eventi poiché lo stesso spostamento del mouse genererebbe componente uscente1 e inserendo componente2. –

risposta

7

Per esempio

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

Controlla i documenti e gli esempi per il "pannello di vetro".
Questo dovrebbe darvi quello che vi serve: The Glass Pane

+0

Potrei usare il pannello di vetro per l'intero frame, ma il componente principale è solo un JPanel che non ha un pannello di vetro. Stavo cercando di mantenere la soluzione localizzata su quel solo componente padre in modo che potesse essere riutilizzata in altre parti dell'app (in cui potrebbe esserci o meno un riquadro di vetro). –

+0

Non sono sicuro che ci sia molta alternativa. Vorrei creare una classe di supporto per installare e interagire con un pannello di vetro. Il pannello può quindi creare un'istanza e interagire con questa classe di supporto, che installerà un riquadro di vetro nella JFrame principale per catturare gli eventi per i limiti del pannello all'interno di quel frame. Quindi gli eventi potrebbero essere inoltrati a un ascoltatore del mouse nominato dal pannello. Quindi tutto il duro lavoro sarebbe fatto dalla classe di supporto e il pannello otterrebbe solo gli eventi che richiede. – davidfrancis

+0

@Jeff Storey [forse non vero affatto] (http: // StackOverflow.it/a/9734016/714968) – mKorbel

1

È possibile avviare una singola istanza del listener e aggiungere tale istanza a ciascun componente. Ti piace questa:

AMouseListener aMouseListener=new AMouseListener(); 

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

David, sì, potrei farlo. La mia preoccupazione era con l'ordine degli eventi. Se è possibile garantire il comportamento mouseExited/mouseEntered, questo è un problema semplice. –

+0

L'hai provato? So che è ovvio, ma provalo a esaminare i componenti e vedere cosa produce. –

+0

Certo, ma anche se funziona, non sono sicuro di quali (se ce ne sono) garanzie sull'ordinazione. –

Problemi correlati