Java Swing:在鼠标悬停时更改背景色
我已经实现了一个简单的鼠标侦听器,当鼠标进入组件(JPanel)时,背景颜色会改变,当鼠标离开时,背景颜色会恢复。这有一些问题:Java Swing:在鼠标悬停时更改背景色,java,swing,mouse,background,mouseout,Java,Swing,Mouse,Background,Mouseout,我已经实现了一个简单的鼠标侦听器,当鼠标进入组件(JPanel)时,背景颜色会改变,当鼠标离开时,背景颜色会恢复。这有一些问题: 有时,鼠标移动得太快,以至于没有触发mouseExit事件 如果我的组件有child,当鼠标移动到child时,它会触发mouseExit 如果我将鼠标快速移动到孩子的身上,则不会触发mouseEnter事件 我猜这对摇摆老手来说很容易。有没有关于如何解决这个问题的建议?我不想使用计时器之类的…有很多解决方案: 将鼠标侦听器添加到子组件。还有容器侦听器,用于在添
- 有时,鼠标移动得太快,以至于没有触发mouseExit事件
- 如果我的组件有child,当鼠标移动到child时,它会触发mouseExit
- 如果我将鼠标快速移动到孩子的身上,则不会触发mouseEnter事件
我猜这对摇摆老手来说很容易。有没有关于如何解决这个问题的建议?我不想使用计时器之类的…有很多解决方案:
- 将鼠标侦听器添加到子组件。还有容器侦听器,用于在添加和删除组件时添加和删除侦听器。不幸的是,添加鼠标侦听器打乱了鼠标事件的冒泡(可怕的设计)
- 在顶部添加一个玻璃窗格。这是非常丑陋的,事件的转发总是会引起问题
- 将
添加到默认的AWTEventListener
中,并筛选出您感兴趣的事件。不幸的是,这需要安全许可Toolkit
- 推送自定义
并过滤事件。这需要一个安全权限,put小程序和WebStart/JNLP应用程序无论如何都会获得该权限EventQueue
- 我无法重现这种行为。请编辑您的问题,以提供演示该问题的简短代码示例
当我创建一个JPanel并在其中放入一些东西时,当鼠标移动到JPanel的子组件上时,JPanel不会得到mouseExit。我猜你给孩子们增加了鼠标听筒
如果我把鼠标移到孩子们身上
很快,mouseEnter事件就不存在了
发射
我从未见过这种情况发生,但如果这是一个问题,那么您可以处理mouseMoved来重置背景
如果我的组件有child,则
鼠标移动到它所触发的孩子
穆塞西特
使用以下测试,代码将仅在离开组件边界时执行:
public void mouseExited(MouseEvent e)
{
if (! getVisibleRect().contains(e.getPoint()) )
{
setBackground(...);
}
}
在容器上尝试了各种方法之后,没有成功,我最终使用了计时器。我的容器包含已经需要鼠标侦听器的元素,这对我没有帮助 计时器方法也意味着我可以将更改延迟一小段时间。(在本例中,我在树节点(容器)中显示其他按钮,并更改背景。) 在容器上的mouseenterned()上,会创建一个计时器(如果还没有),该计时器每260毫秒重复一次。每次调用计时器时,它都会确定鼠标是否在容器内。如果是这样的话,在第一次发出鼠标悬停的信号时。如果没有,它会发出非鼠标移动的信号并停止计时器 在Scala中,这如下所示,其中对entryExit()的方法调用对鼠标是否结束进行编码(其中具有相同值的多个调用没有影响):
我试过玻璃窗,但没有用。我可以将玻璃窗格应用于简单的JPanel吗?我以为你只能用在JFrames上。因为我有多个JPanel,所以我真的需要对每个JPanel应用玻璃窗格。是的,你是对的。我尝试将鼠标侦听器添加到子对象。如果将指针从外部移动到包含的子对象(使用鼠标侦听器),则父容器上的鼠标侦听器将不会被触发。慢慢地把它移到边界区域,它就会移动。我把你的技术和汤姆·霍丁的技术结合起来。不幸的是,你们中只有一个人能得到正确的答案。谢谢大家。
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()
}
}
...
}