将事件传递给父母
我想创建一个应用程序,其中一些事件应该被处理,好像它们被传递到父容器一样。 例如,我有一个包含JLabel的JPanel。 顶级JPanel现在实现了鼠标拖动和拖动。 我需要做什么,以使事件看起来像他们到达JPanel而不是标签本身。 (更改源对象很重要)
有没有比实际实现事件并在父代中复制它们更好的解决方案? (在一些具有> 5个孩子的物体之后,这将变得乏味)。
在事件监听器中,您可以将事件分派给父组件。
作为myEvent
的事件处理函数参数:
Component source=(Component)myEvent.getSource(); source.getParent().dispatchEvent(myEvent);
但是这个解决方案意味着为要添加的每个元素创建一个新的EventListener。
因此,您可以创建单个事件处理程序并重用它,将其添加到所有选定的子项中,如下所示:
final Container parent=this; //we are a the parent container creation code MouseListener myCommonListener=new MouseListener() { @Override public void mouseClicked(MouseEvent e) { parent.dispatchEvent(e); } @Override public void mouseEntered(MouseEvent e) { parent.dispatchEvent(e); } @Override public void mouseExited(MouseEvent e) { parent.dispatchEvent(e); } @Override public void mousePressed(MouseEvent e) { parent.dispatchEvent(e); } @Override public void mouseReleased(MouseEvent e) { parent.dispatchEvent(e); } }; JLabel label=new JLabel("This is the first Label"); label.addMouseListener(myCommonListener); JLabel label2=new JLabel("This is the second Label"); label2.addMouseListener(myCommonListener); //... and so on
您应该在将事件分派给父级之前转换事件。 转换包括到父亲亲属的坐标转换。
public class RedispatchingMouseAdapter implements MouseListener, MouseWheelListener, MouseMotionListener{ public void mouseClicked(MouseEvent e) { redispatchToParent(e); } public void mousePressed(MouseEvent e) { redispatchToParent(e); } public void mouseReleased(MouseEvent e) { redispatchToParent(e); } public void mouseEntered(MouseEvent e) { redispatchToParent(e); } public void mouseExited(MouseEvent e) { redispatchToParent(e); } public void mouseWheelMoved(MouseWheelEvent e){ redispatchToParent(e); } public void mouseDragged(MouseEvent e){ redispatchToParent(e); } public void mouseMoved(MouseEvent e) { redispatchToParent(e); } private void redispatchToParent(MouseEvent e){ Component source = (Component) e.getSource(); MouseEvent parentEvent = SwingUtilities.convertMouseEvent(source, e, source.getParent()); source.getParent().dispatchEvent(parentEvent); } }
鼠标事件自动定位到具有鼠标侦听器的最深部件。
因此,为了实现您的目标,您可以简单地删除JLabel上的所有鼠标侦听器,它永远不会被选为鼠标事件的目标。
以下代码将以递归方式禁用给定组件及其子组件上的鼠标侦听器:
private void disableMouseForComponent(Component... components) { for (Component c : components) { if (c instanceof Container) { disableMouseForComponent(((Container) c).getComponents()); } for (MouseListener l : c.getMouseListeners()) { c.removeMouseListener(l); } for (MouseMotionListener l : c.getMouseMotionListeners()) { c.removeMouseMotionListener(l); } } }