我有一个使用BorderLayout
的JPanel
,它有2个组件。NORTH
中有一个JLabel
, CENTER
中有一个JList
。
我已经在面板上添加了一个MouseListener
,并且现在编码了一个消息框出现在mouseEntered
上。
问题是只有当光标进入标签占用的区域时才会触发该事件。我需要当鼠标进入整个面板区域时触发事件。
知道我做错了什么吗?
编辑:代码创建面板
JPanel p = new JPanel();
p.setLayout(new BorderLayout());
p.add(new JLabel("Label"), BorderLayout.NORTH);
p.add(new JList(), BorderLayout.CENTER);
p.addMouseListener(new MouseListener(){
@Override
public void mouseEntered(MouseEvent e) {
JOptionPane.showMessageDialog(null, "Entered Panel");
}
//Other overriden methods
...
});
从jdk7开始,您可以用JLayer装饰任何JComponent,并注册该层以接收分派给其子组件的所有事件,如
JTable list = new JTable(30, 5);
JComponent panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createEmptyBorder(50, 50, 50, 50));
panel.add(new JLabel("we are label"));
panel.add(new JScrollPane(list));
LayerUI<JComponent> ui = new LayerUI<JComponent>() {
@Override
protected void processMouseEvent(MouseEvent e, JLayer<? extends JComponent> l) {
if (e.getID() == MouseEvent.MOUSE_ENTERED) {
System.out.println(e.getSource().getClass() + " at " + e.getPoint());
}
}
};
JLayer<JComponent> layer = new JLayer<JComponent>(panel, ui);
layer.setLayerEventMask(AWTEvent.MOUSE_EVENT_MASK );
注意,这是由一个AWTEventListener内部处理的,就像Rob的博客中建议的解决方案一样。与Rob的解决方案相比,它的优点是它也可以在沙盒环境中工作(作为一个核心类,JLayer具有必要的特权)。
对于早期的jdk版本,有一个项目JXLayer (SwingLabs的一部分),它是新核心类的直接前身。它没有权限问题,因为它在内部使用了一种稍微不同的方法来获取所有事件。
我认为问题在于JList是接收鼠标事件的组件。我不确定这是否是处理该问题的最佳方法,但是您不能也将相同的鼠标侦听器添加到JList中吗?
任何具有MouseListener的组件都将接收鼠标事件,而不会将其传递给面板。
你可以给每个组件添加一个mousellistener,但是如果面板的设计改变了怎么办?不要忘记,您可能在JList的右侧有一个滚动条,因此,如果用户从右侧进入面板,则在鼠标从滚动条移动到列表上之前不会生成事件。
相反,您可能需要考虑使用全局事件侦听器来侦听mouseEntered事件。然后,当接收到事件时,需要检查事件的源是面板本身还是面板的子组件。您应该能够使用:
SwingUtiltities.isDescendingFrom(...)