2009-12-10 6 views
4

J'ai implémenté un simple écouteur souris où la couleur d'arrière-plan change à chaque fois que la souris entre dans le composant (un JPanel), et revient à chaque fois que la souris quitte. Cela a des problèmes:Java Swing: changer la couleur d'arrière-plan sur la souris

  • Parfois, la souris se déplace si vite que le mouseExit événement ne se déclenche pas
  • Si mon composant a Childs, lorsque la souris passe aux Childs il déclenche l'mouseExit
  • Si je déplace la souris sur les Childs rapidement, l'événement mouseEnter ne se déclenche pas

Je devine que c'est un ea un pour les vétérans de Swing. Des suggestions sur la façon de résoudre ce problème? J'aimerais ne pas utiliser des minuteries et autres ...

Répondre

6

Si je déplace la souris sur les Childs rapidement, l'événement mouseEnter n'est pas tiré

Je ne l'ai jamais vu que cela se produise, mais si elle est un problème, vous pouvez gérer mouseMoved à la place pour réinitialiser l'arrière-plan.

Si mon composant a Childs, lorsque les souris se déplace aux Childs il déclenche le mouseExit

Utilisez le test et le code suivant ne sera exécuté que lorsque vous quittez les limites des composants:

public void mouseExited(MouseEvent e) 
{ 
    if (! getVisibleRect().contains(e.getPoint())) 
    { 
     setBackground(...); 
    } 
} 
+0

Si vous déplacez le pointeur de l'extérieur vers un enfant contenu (avec un écouteur souris), un écouteur souris sur le conteneur parent ne sera pas déclenché. Déplacez-le lentement sur une région frontalière et il le fera. –

+0

J'ai utilisé un mélange de votre technique et de Tom Hawtin. Malheureusement, un seul d'entre vous peut obtenir la bonne réponse. Merci a tous. –

3

Il y a un certain nombre de solutions:

  • Ajouter les auditeurs de souris aux composants de l'enfant. Également les écouteurs de conteneur, pour ajouter et supprimer des écouteurs en tant que composants sont ajoutés et supprimés. Malheureusement, l'ajout d'auditeurs de souris bouleverse les événements de la souris (conception hideuse).
  • Ajouter une vitre sur le dessus. C'est vraiment moche, et la transmission des événements cause toujours des problèmes.
  • Ajouter un AWTEventListener à la valeur par défaut Toolkit et filtrer pour les événements qui vous intéressent. Cela nécessite malheureusement une Autorisation de Sécurité.
  • Pousser un EventQueue personnalisé et filtrer les événements. Cela nécessite une autorisation de sécurité, mettre les applets et les applications WebStart/JNLP obtenir cette autorisation de toute façon.
+0

I J'ai essayé la vitre sans succès. Puis-je appliquer des vitres sur des JPanels simples? Je pensais que vous ne pouviez l'appliquer qu'à JFrames. Comme j'ai plusieurs JPanels, j'ai vraiment besoin d'appliquer le volet de verre à chacun d'entre eux. –

0

Je ne peux pas reproduire ce comportement. Veuillez modifier votre question pour fournir un exemple de code court qui illustre le problème.

Lorsque je crée un JPanel et y place quelque chose, le JPanel n'est pas mouseExit lorsque la souris se déplace sur un composant enfant du JPanel. Je suppose que vous avez ajouté MouseListeners aux enfants.

+0

Oui, vous avez raison. J'ai essayé d'ajouter des écouteurs de souris aux enfants. –

1

Après avoir essayé différentes approches sur un conteneur, sans succès, je me suis retrouvé à l'aide d'une minuterie .Cela n'a pas aidé que mon conteneur contenait des éléments qui avaient déjà besoin d'écouteurs de souris.

L'approche de la minuterie signifiait également que je pouvais retarder le changement pendant une courte période. (Dans mon cas, je montre des boutons supplémentaires dans un nœud d'arbre (un récipient), ainsi que de changer l'arrière-plan.)

Sur un mouseEntered() sur le récipient, une minuterie est créé (sinon là déjà) qui se répète toutes les 260 millisecondes. À chaque appel du temporisateur, il détermine si la souris est à l'intérieur du conteneur. Si c'est le cas, la première fois, il signale le passage de la souris. Si ce n'est pas le cas, il signale qu'il n'y a pas de souris et arrête le chronomètre.

En Scala, est la suivante, où l'appel de méthode pour entryExit() encode si la souris est terminée ou non (où plusieurs appels avec la même valeur ont aucun):

abstract class MouseInterpreter(component: JComponent) extends MouseAdapter { 
    ... 
    private var mouseOverAction:() => Unit =() => {} 
    private var mouseOverTimer: Option[Timer] = None 
    ... 
    def entryExit(entered: Boolean) // this is an abstract method 

    override def mouseEntered(e: MouseEvent) { 
    if (mouseOverTimer.isEmpty) { 
     val aTimer = new Timer(260, new ActionListener { 
     def actionPerformed(e: ActionEvent) { 
      mouseOverAction() 
     } 
     }) 
     mouseOverTimer = Some(aTimer) 
     mouseOverAction =() => { 
     mouseOverAction =() => { 
      val point = MouseInfo.getPointerInfo.getLocation 
      SwingUtilities.convertPointFromScreen(point, component) 
      if (component.getVisibleRect.contains(point)) 
      entryExit(entered = true) 
      else { 
      entryExit(entered = false) 
      aTimer.stop() 
      mouseOverTimer = None 
      mouseOverAction =() => {} 
      } 
     } 
     } 
     aTimer.setRepeats(true) 
     aTimer.start() 
    } 
    } 
... 
} 
Questions connexes