在 World Wind 中点击禁用地球运动

Disable globe movement on click in World Wind

我试图在 World Wind 中禁用鼠标点击时地球仪的移动。我希望能够做到:

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

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

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 只是在 java.awt.Component 上调用 addMouseMotionListener() 所以显然我不明白消费事件是如何工作的。

更新 2: 尽管与 Swing 共享接口,使用 AWTInputHandler 作为参数调用 WorldWindowGLCanvas.removeMouseMotionListener() 将阻止所有其他 MouseMotionListeners接收事件。应改用 AWTInputHandler 上的添加和删除方法。

为什么不起作用:

如前所述,here, many event sources maintain an EventListenerList. The prescribed scheme allows an arbitrary number of listeners to be added or removed. This related example 列出了注册到文本组件 DocumentDocumentListener 的所有实例。没有一个听众抢占另一个。

你可能会做什么:

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

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

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

引用世界风的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()

在努力想办法做到这一点并偶然发现这个解决方案之后,我相信我已经想出了“正确”的解决方案。完全删除鼠标运动侦听器在技术上可行,但它会破坏其他可能有用的功能(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"/>

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

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