Java Swing: change background color on mouse over

爱⌒轻易说出口 提交于 2019-12-17 20:25:09

问题


I've implemented a simple mouse listener where the background color changes whenever the mouse enters the component (a JPanel), and it reverts back whenever the mouse leaves. This has some problems:

  • Sometimes the mouse moves so quick that the mouseExit event is not fired
  • If my component has childs, when the mouse moves to the childs it triggers the mouseExit
  • If I move the mouse over to the childs quickly, the mouseEnter event is not fired

I'm guessing this is an easy one for Swing veterans. Any suggestions on how to fix this? I'd love not to use timers and such...


回答1:


If I move the mouse over to the childs quickly, the mouseEnter event is not fired

I've never seen this to happen, but if it is an issue then you can handle mouseMoved instead to reset the background.

If my component has childs, when the mouse moves to the childs it triggers the mouseExit

Use the following test and the code will only be executed when you leave the components bounds:

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



回答2:


There are a number of solutions:

  • Add mouse listeners to the child components. Also container listeners, to add and remove listeners as components are added and removed. Unfortunately adding mouse listeners upset bubbling up of mouse events (hideous design).
  • Add a glass pane over the top. This is mighty ugly, and forwarding of events always causes problems.
  • Add an AWTEventListener to the default Toolkit and filter through for the events you are interested in. This unfortunately requires a security permission.
  • Push a custom EventQueue and filter events. This requires a security permission, put applets and WebStart/JNLP applications get that permission anyway.



回答3:


After trying various approaches on a container, without success, I ended up using a Timer. It didn't help that my container contained elements that already needed mouse listeners on them.

The timer approach also meant that I could delay the change for a short time. (In my case, I show additional buttons in a tree node (a container), as well as changing the background.)

On a mouseEntered() on the container, a Timer is created (if not there already) which repeats every 260 milliseconds. On each call of the Timer, it determines whether the mouse is inside the container. If so, on the first time it signals mouse-over. If not, it signals non-mouse-over and stops the timer.

In Scala, this is as follows, where the method call to entryExit() encodes whether the mouse is over or not (where multiple calls with the same value have no affect):

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



回答4:


I can't reproduce this behavior. Please edit your question to provide a short code sample that demonstrates the problem.

When I create a JPanel, and put something in it, the JPanel does not get mouseExit when the mouse moves over a child component of the JPanel. I'm guessing that you've added MouseListeners to the children.



来源:https://stackoverflow.com/questions/1882055/java-swing-change-background-color-on-mouse-over

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!