4

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

  • 有时鼠标移动得太快以至于不会触发mouseExit事件
  • 如果我的组件有孩子,当鼠标移动到孩子时,它会触发mouseExit
  • 如果我将鼠标快速移到孩子身上,则不会触发mouseEnter事件

我猜这对于 Swing 退伍军人来说是一件容易的事。对于如何解决这个问题,有任何的建议吗?我不想使用计时器之类的......

4

4 回答 4

6

如果我将鼠标快速移到孩子身上,则不会触发 mouseEnter 事件

我从未见过这种情况发生,但如果这是一个问题,那么您可以处理 mouseMoved 来重置背景。

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

使用以下测试,代码将仅在您离开组件边界时执行:

public void mouseExited(MouseEvent e) 
{
    if (! getVisibleRect().contains(e.getPoint()) )
    {
        setBackground(...);
    }
}
于 2009-12-10T16:19:41.573 回答
3

有多种解决方案:

  • 将鼠标侦听器添加到子组件。还有容器侦听器,用于在添加和删除组件时添加和删除侦听器。不幸的是,添加鼠标侦听器会扰乱鼠标事件的冒泡(可怕的设计)。
  • 在顶部添加一个玻璃窗格。这非常丑陋,并且转发事件总是会导致问题。
  • 添加一个AWTEventListener到默认值Toolkit并过滤您感兴趣的事件。不幸的是,这需要安全权限。
  • 推送自定义EventQueue和过滤事件。这需要安全权限,put 小程序和 WebStart/JNLP 应用程序无论如何都会获得该权限。
于 2009-12-10T16:16:52.227 回答
1

在容器上尝试了各种方法后,没有成功,我最终使用了Timer。我的容器包含已经需要鼠标侦听器的元素并没有帮助。

计时器方法还意味着我可以将更改延迟一小段时间。(在我的例子中,我在树节点(容器)中显示了额外的按钮,以及更改背景。)

在容器上的mouseEntered()上,会创建一个Timer(如果还没有的话),它每 260 毫秒重复一次。在每次调用 Timer 时,它会确定鼠标是否在容器内。如果是这样,它会在第一次发出鼠标悬停信号。如果不是,它会发出非鼠标悬停信号并停止计时器。

在 Scala 中,如下所示,其中对entryExit()的方法调用对鼠标是否悬停进行编码(具有相同值的多次调用没有影响):

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()
    }
  }
...
}
于 2013-10-11T22:24:09.600 回答
0

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

当我创建一个 JPanel 并在其中放入一些东西时,当鼠标移到 JPanel 的子组件上时,JPanel 不会获得 mouseExit。我猜你已经为孩子们添加了 MouseListeners。

于 2009-12-10T16:19:16.520 回答