JPanel在子组件上时无法生成鼠标事件。

4

对我来说有点奇怪,但是当鼠标指针位于子组件:JTextField和JToolBar上时,JPanel不会生成MouseEvents,但当鼠标指针位于JLabel上时,它会生成MouseEvents。有人能解释一下为什么吗?是否有办法强制JPanel生成事件,即使鼠标位于子组件上?


2
你能否发布一两个相关代码片段? - jjnguy
3个回答

3
事件分派程序将鼠标事件转发到由Container中的包级别getMouseEventTarget方法返回的组件上注册的侦听器。该方法将在您的JFrame上调用,并且如JavaDoc所示,它会:

获取最深处对接收鼠标事件感兴趣的轻量级组件。

然后,事件分派程序将获取这个最顶层组件(例如您的JTextField)并仅向其所有侦听器发送事件。他们这样做是为了避免将这些事件广播到可能位于Swing容器内部的所有组件。可以想象,鼠标事件非常繁琐,因为所有可能存在的MouseListenerMouseMotionListener实现都会发出mouseEnteredmouseDraggedmouseMoved事件。找到所有侦听器并将事件发送到层次结构中的所有侦听器的处理将耗费很长时间。
还假设像JTextFieldJButton等类的默认鼠标处理是人们需要的全部。如果您想以不同方式处理鼠标操作(例如,在mouseEntered/mouseExited上更改颜色),则可以根据需要将MouseListener添加到这些小部件中。
对于您的处理,建议如果需要处理这些事件,只需将您的JPanel作为MouseListener添加到顶层组件中即可。

+1 有趣; getMouseEventTarget()java.awt 中是 _包访问权限_(没有明确的修饰符),但大多数 IDE 允许浏览源代码。 - trashgod

2

您可能希望让子组件(如JTextField、JToolBar等)监听来自JPanel的鼠标事件,或将鼠标事件转发到子组件。


+1 我认为转发是正确的想法,但 @guest 可能希望像这个例子中建议的那样,将子组件的事件转发到父 JPanel。https://dev59.com/e0vSa4cB1Zd3GeqPf6K- - trashgod

1
有人能解释一下为什么吗? processMouseEvent() 处理 {{Component}} 鼠标事件,它说:
鼠标事件在以下情况下启用:
  • 通过 addMouseListener 注册 MouseListener 对象。
  • 通过 enableEvents 启用鼠标事件。
你可以使用 getMouseListeners() 来查看区别。

+1,很棒,我不知道有一个getMouseListeners()方法存在。我一直使用通用的getListeners(...)方法。这将使未来的生活更轻松一些。 - camickr
жңүи¶ЈпјӣжҲ‘дёҚзҹҘйҒ“getListeners()ж”ҜжҢҒзұ»еӯ—йқўзұ»еһӢж Үи®°пјҢе°ұеғҸEventListenerListдёҖж ·гҖӮдёҚе№ёзҡ„жҳҜпјҢ+1еҘҪеғҸж¶ҲеӨұдәҶгҖӮ :-) - trashgod
糟糕...发现了 +1。 - camickr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接