繁体   English   中英

Java Swing:在鼠标悬停时更改背景颜色

[英]Java Swing: change background color on mouse over

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

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

我猜这对于Swing老兵来说很简单。 对于如何解决这个问题,有任何的建议吗? 我不想使用计时器等......

如果我将鼠标快速移动到子节点,则不会触发mouseEnter事件

我从来没有见过这种情况,但如果它是一个问题,那么你可以处理mouseMoved而不是重置背景。

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

使用以下测试,只有在离开组件边界时才会执行代码:

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

有很多解决方案:

  • 将鼠标侦听器添加到子组件。 还有容器侦听器,用于在添加和删除组件时添加和删除侦听器。 不幸的是,添加鼠标监听器会扰乱鼠标事件(丑陋的设计)。
  • 在顶部添加玻璃窗格。 这是非常丑陋的,事件的转发总是会引起问题。
  • AWTEventListener添加到默认Toolkit并过滤您感兴趣的事件。遗憾的是,这需要安全权限。
  • 推送自定义EventQueue并过滤事件。 这需要安全权限,applet和WebStart / JNLP应用程序无论如何都要获得该权限。

在对容器尝试各种方法后,没有成功,我最终使用了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()
    }
  }
...
}

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM