4

我试图在 World Wind 中通过鼠标单击来禁用地球的移动。我希望能够做到:

void disableGlobeDrag(WorldWindowGLCanvas ww) {
    ww.addMouseMotionListener(new MyMouseMotionListener());
}

whereMyMouseMotionListener消耗所有的鼠标事件。这不起作用,所以我必须这样做:

void disableGlobeDrag(WorldWindowGLCanvas ww) {
    for(MouseMotionListener l : ww.getMouseMotionListeners()) {
        if(l.getClass().toString().equals("class gov.nasa.worldwind.awt.AWTInputHandler")) {
            ww.removeMouseMotionListener(l);
        }
    }
}

是否预期消耗的鼠标事件仍应到达gov.nasa.worldwind.awt.AWTInputHandler侦听器?

更新: WorldWindowGLCanvas只是打电话addMouseMotionListener()java.awt.Component所以显然我不明白消费事件是如何工作的。

更新 2:尽管与 Swing 共享接口,但调用WorldWindowGLCanvas.removeMouseMotionListener()withAWTInputHandler作为参数将阻止所有其他MouseMotionListeners 接收事件。AWTInputHandler应该使用add 和 remove 方法。

4

3 回答 3

3

不幸的是,MouseMotionListener按照@trashgod 的建议删除并不起作用,因为发生了一些 World Wind 特定的行为:删除gov.nasa.worldwind.awt.AWTInputHandler会导致其他MouseMotionListeners 停止接收事件通知。

要禁用地球拖动并仍然在另一个中接收事件,MouseMotionListener需要执行以下步骤:

获取对 World Wind 的参考AWTInputHandler

AWTInputHandler wwHandler = null;
// get World Wind's AWTInputHandler class:
for (MouseMotionListener l : ww.getMouseMotionListeners()) {
    if(l instanceof AWTInputHandler) {
        wwHandler = (AWTInputHandler)l;
        break;
    }
}

创建一个MouseMotionListener消费事件的:

public class MyMouseMotionListener implements MouseMotionListener {
    @Override
    public void mouseDragged(MouseEvent e) {
        // consume the event so the globe position does not change
        e.consume();
        if (e.getSource() instanceof WorldWindowGLCanvas) {
            // get the position of the mouse
            final WorldWindowGLCanvas canvas = ((WorldWindowGLCanvas) e.getSource());
            final Position p = canvas.getCurrentPosition();
            // do something with the position here
        }
    }
    @Override
    public void mouseMoved(MouseEvent e) {
        e.consume();
    }
}

将鼠标运动侦听器添加到AWTInputHandler

if(wwHandler != null) {
    wwHandler.addMouseMotionListener(new MyMouseMotionListener());
} else {
    // I don't think this should happen unless the AWTInputHandler
    // is explicitly removed by client code
    logger.error("Couldn't find AWTInputHandler");
}

也就是说,我不知道为什么WorldWindowGLCanvas使用Component.addMouseMotionListener()而不是AWTInputHandler.addMouseMotionListener().

于 2015-07-14T21:47:32.273 回答
2

为什么它不起作用:

正如这里所讨论的,许多事件源维护一个EventListenerList. 规定的方案允许添加或删除任意数量的侦听器。这个相关示例列出了所有DocumentListener注册到文本组件的Document. 没有一个听众会抢占另一个听众。

你可能会做什么:

给定 a 的实例WorldWindowGLCanvas,您可能会查看由返回的数组,getMouseMotionListeners()并根据需要调用removeMouseMotionListener()

于 2015-07-14T21:14:42.767 回答
1

在努力解决这个问题并偶然发现这个解决方案之后,我相信我已经想出了“正确”的解决方案。完全删除鼠标运动侦听器在技术上确实有效,但它会破坏其他可能有用的功能(KML 树节点选择,屏幕视图控件)。

创建一个输入处理程序的子类以删除“移动到”功能

public class MyOrbitViewInputHandler extends OrbitViewInputHandler
{
  public MyOrbitViewInputHandler()
  {
    // Disable single click to pan functionality
    ViewInputAttributes.ActionAttributes actionAttrs =
      this.getAttributes().getActionMap(ViewInputAttributes.DEVICE_MOUSE).getActionAttributes(ViewInputAttributes.VIEW_MOVE_TO);
    actionAttrs.setMouseActionListener(null);
  }
}

在 worldwind.xml 配置文件中指定新的输入处理程序

<Property name="gov.nasa.worldwind.avkey.ViewInputHandlerClassName"
          value="mil.dtra.nucs.coe.ui.map.MyOrbitViewInputHandler"/>

使用此方法,画布上发生的所有其他鼠标交互仍将正常工作,但删除了“单击平移”功能。

如果您对可能会覆盖的其他行为感到好奇,您可以查看 gov.nasa.worldwind.awt.BasicViewInputHandler

于 2017-05-16T17:41:48.370 回答