基本上,当鼠标进入JPanel区域并退出JPanel区域时,我想知道一个JPanel。所以我添加了一个鼠标监听器,但是如果JPanel上有组件并且鼠标经过其中一个组件,则它被检测为JPanel上的一个出口,即使该组件位于JPanel上。我想知道是否有人知道如何解决这个问题,而不需要像在JPanel上的所有组件上添加监听器那样?
答案 0 :(得分:9)
有一个非常简单的解决方案可以解决这个问题:
public class MyJPanel implements MouseListener {
public void mouseExited(MouseEvent e) {
java.awt.Point p = new java.awt.Point(e.getLocationOnScreen());
SwingUtilities.convertPointFromScreen(p, e.getComponent());
if(e.getComponent().contains(p)) {return;}
...//the rest of your code
}
...
}
这样,只要在子元素上发生mouseExited事件,就会忽略它。
答案 1 :(得分:8)
以下是为可能包含其他组件的组件执行此操作的一种方法:
添加全局AWT事件侦听器以获取所有鼠标事件。例如:
Toolkit.getDefaultToolkit().addAWTEventListener(
new TargetedMouseHandler( panel ), AWTEvent.MOUSE_EVENT_MASK );
实施TargetedMouseHandler
以忽略非由面板或其中一个面板子项提供的事件(您可以使用SwingUtilities.isDescendingFrom
对此进行测试)。
跟踪鼠标是否已经在面板的范围内。当您在面板或其中一个子项中收到MouseEvent.MOUSE_ENTERED
事件时,请将标记设置为true。
当您收到MouseEvent.MOUSE_EXITED
事件时,如果MouseEvent
中的点超出目标面板的范围,则只重置该标记。 SwingUtilities.convertPoint
和Component.getBounds().contains()
会派上用场。
答案 2 :(得分:4)
这是实施Ash解决方案的示例代码。对我来说,JFrame没有正确检测所有退出事件,但内部JPanel没有检测到,所以我传入了两个组件 - 一个用于测试后代,另一个用于测试边界。
Toolkit.getDefaultToolkit().addAWTEventListener(
new TargetedMouseHandler(this, this.jPanel),
AWTEvent.MOUSE_EVENT_MASK);
}
public class TargetedMouseHandler implements AWTEventListener
{
private Component parent;
private Component innerBound;
private boolean hasExited = true;
public TargetedMouseHandler(Component p, Component p2)
{
parent = p;
innerBound = p2;
}
@Override
public void eventDispatched(AWTEvent e)
{
if (e instanceof MouseEvent)
{
if (SwingUtilities.isDescendingFrom(
(Component) e.getSource(), parent))
{
MouseEvent m = (MouseEvent) e;
if (m.getID() == MouseEvent.MOUSE_ENTERED)
{
if (hasExited)
{
System.out.println("Entered");
hasExited = false;
}
} else if (m.getID() == MouseEvent.MOUSE_EXITED)
{
Point p = SwingUtilities.convertPoint(
(Component) e.getSource(),
m.getPoint(),
innerBound);
if (!innerBound.getBounds().contains(p))
{
System.out.println("Exited");
hasExited = true;
}
}
}
}
}
}
答案 3 :(得分:0)
如果要将所有事件发送到顶级窗口,可以将侦听器添加到JFrame的玻璃窗格。请参阅:http://java.sun.com/j2se/1.4.2/docs/api/javax/swing/RootPaneContainer.html#getGlassPane%28%29
答案 4 :(得分:0)
使用Java 1.8+的simpeler解决方案
public class MyJPanel implements MouseListener {
public void mouseExited(MouseEvent e) {
if(!this.contains(e.getPoint())) {
... //the rest of your code
}
}
...
}