2009-12-10 100 views
4

我已经实现了一个简单的鼠标监听器,只要鼠标进入组件(一个JPanel),背景颜色就会改变,只要鼠标离开,它就会恢复。这有一些问题:Java Swing:改变鼠标的背景颜色

  • 有时候鼠标移动这么快的mouseExit事件不会触发
  • 如果我的组件有孩子的,当鼠标移动到孩子的它触发mouseExit
  • 如果我快速移动鼠标到孩子的,在的mouseenter事件不会触发

我猜这是一个EA sy一个摆动老兵。对于如何解决这个问题,有任何的建议吗?我很想不使用定时器等...

回答

6

如果我把鼠标移动到孩子的 迅速,MouseEnter事件不 解雇

我从来没有见过这样的事情发生,但如果它是一个问题,那么你可以处理mouseMoved改为重置背景。

如果我的组件有孩子的,当 鼠标移动到孩子的它触发 的mouseExit

使用下面的测试,当你离开组件的边界的代码才会执行​​:

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

如果将指针从外部移动到包含的子项(使用鼠标侦听器),则父容器上的鼠标侦听器将不会被触发。在边界区域缓慢移动它,它会。 – 2009-12-10 17:42:10

+0

我已经使用了你的技术和汤姆霍金的混合。不幸的是,只有其中一个人可以得到正确的答案。谢谢大家。 – 2009-12-10 18:08:17

3

有许多解决方案:

  • 添加鼠标侦听到子组件。也是容器侦听器,添加和删除侦听器,因为组件被添加和删除。不幸的是,添加鼠标听众不满起泡鼠标事件(可怕的设计)。
  • 在顶部添加一个玻璃窗格。这是非常丑陋的,事件的转发总是会引起问题。
  • AWTEventListener添加到默认的Toolkit并过滤您感兴趣的事件。不幸的是需要安全权限。
  • 推送自定义EventQueue并过滤事件。这需要一个安全权限,无论如何,将applet和WebStart/JNLP应用程序获得该权限。
+0

我我已经尝试了玻璃窗,但无济于事。我可以将玻璃窗格应用于简单的JPanel吗?我以为你只能将它应用于JFrames。 由于我有多个JPanels,我真的需要将玻璃板应用到他们中的每一个。 – 2009-12-10 16:20:02

0

我无法重现此行为。请编辑您的问题以提供演示问题的简短代码示例。

当我创建一个JPanel并在其中放入内容时,当鼠标移动到JPanel的子组件上时,JPanel不会获取mouseExit。我猜你已经添加了MouseListeners给孩子们。

+0

是的,你是对的。我试图给孩子添加鼠标监听器。 – 2009-12-10 16:30:23

1

试图容器上各种办法,都没有成功后,我结束了使用定时器。这并没有帮助我的容器包含已经需要鼠标侦听器的元素。

计时器方法还意味着我可以在短时间内延迟更改。 (在我的情况,我将展示在一个树节点(容器)额外的按钮,以及改变背景。)

在一个的mouseEntered()在容器上,一个定时器创建(如果不是已经有),每260毫秒重复一次。在每次调用Timer时,都会确定鼠标是否在容器内。如果是这样,它第一次发信号通知鼠标悬停。如果不是,则它表示非鼠标悬停并停止定时器。

在Scala中,这是如下,其中方法调用到出入境()编码小鼠是否结束与否(其中具有相同值的多个调用就没有影响):

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