Frage

Ich habe einen einfachen Maushörer implementiert, bei dem sich die Hintergrundfarbe ändert, wenn die Maus in die Komponente (ein JPanel) eintritt, und sie kehrt zurück, wenn die Maus geht. Dies hat einige Probleme:

  • Manchmal bewegt sich die Maus so schnell, dass die Mouseexit Ereignis wird nicht entlassen
  • Wenn meine Komponente Kind hat, wenn sich die Maus zu den Kinden bewegt, löst sie das aus Mouseexit
  • Wenn ich die Maus schnell zu den Kinden überlagst, die Mouseenter Ereignis wird nicht entlassen

Ich vermute, dies ist einfach für Swing -Veteranen. Irgendwelche Vorschläge, wie man das behebt? Ich würde gerne keine Timer und dergleichen verwenden ...

War es hilfreich?

Lösung

Wenn ich die Maus schnell zu den Kinden bewege, wird das Mouseenter -Ereignis nicht abgefeuert

Ich habe dies noch nie gesehen, aber wenn es sich um ein Problem handelt, können Sie stattdessen mit Mousemoved handeln, um den Hintergrund zurückzusetzen.

Wenn meine Komponente Kind hat, wenn sich die Maus zu den Kinden bewegt, löst sie den Mouseexit aus

Verwenden Sie den folgenden Test und der Code wird nur ausgeführt, wenn Sie die Komponentengrenzen hinterlassen:

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

Andere Tipps

Es gibt eine Reihe von Lösungen:

  • Fügen Sie den Kinderkomponenten Maushörer hinzu. Auch Containerhörer, um Hörer hinzuzufügen und zu entfernen, wenn Komponenten hinzugefügt und entfernt werden. Das Hinzufügen von Maushörern verärgerte sich leider mit Mausereignissen (abscheuliches Design).
  • Fügen Sie eine Glasscheibe darüber hinzu. Dies ist mächtig hässlich, und die Weiterleitung von Ereignissen verursacht immer Probleme.
  • Fügen Sie ein hinzu AWTEventListener zum Standard Toolkit und filtern Sie für die Ereignisse, an denen Sie interessiert sind. Dies erfordert leider eine Sicherheitsgenehmigung.
  • Schieben Sie einen Brauch EventQueue und Filterereignisse. Dies erfordert eine Sicherheitsberechtigung, setzen Sie Applets und Webstart/JNLP -Anwendungen ohnehin ein.

Nachdem ich verschiedene Ansätze in einem Behälter ohne Erfolg ausprobiert hatte, verwendete ich ein Timer. Es half nicht, dass mein Container Elemente enthielt, die bereits Maushörer auf ihnen benötigten.

Der Timer -Ansatz bedeutete auch, dass ich die Änderung für kurze Zeit verzögern konnte. (In meinem Fall zeige ich zusätzliche Schaltflächen in einem Baumknoten (einem Behälter) sowie den Hintergrund ändern.)

Auf einen mausented () Auf dem Behälter a Timer wird erstellt (wenn nicht bereits da), was alle 260 Millisekunden wiederholt. Auf jedem Ruf des Timers bestimmt es, ob sich die Maus im Behälter befindet. Wenn ja, signalisiert es beim ersten Mal Maus. Wenn nicht, signalisiert es Nicht-Maus und stoppt den Timer.

In Scala ist dies wie folgt, wo die Methode aufgerufen wird EntryExit () codiert, ob die Maus vorbei ist oder nicht (wobei mehrere Aufrufe mit demselben Wert keinen Einfluss haben):

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()
    }
  }
...
}

Ich kann dieses Verhalten nicht reproduzieren. Bitte bearbeiten Sie Ihre Frage, um ein kurzes Code -Beispiel anzugeben, das das Problem demonstriert.

Wenn ich ein JPANEL erstelle und etwas darin einsetzt, bekommt das JPanel nicht Mouseexit, wenn sich die Maus über eine Kinderkomponente des JPanel bewegt. Ich vermute, dass Sie den Kindern Mouselistener hinzugefügt haben.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top