Skip to content

MITK交互

1 屏蔽键盘交互

基于mitk框架开发的交互通过 statemachine 和 config 的配置文件件实现自定义。mitk(vtk)默认操作,按下不同按键+左键实现不同操作,不同按键还有组合,比如 shift+ctrl+左键 缩放模型。实际给用户使用时不需要这么多操作。

项目中把所有xml交互全部重新定义过,还拓展了很多自定义交互。交付给用户使用后偶现了一次鼠标无法交互模型。排查后发现是由于键盘某个按键被卡住了。需要调整为 shift alt ctrl 无论按下一个还是多个,均可以通过左键旋转,中键平移。

没有找到可以直接屏蔽的设置,先尝试通过加 <attribute name="Modifiers" value="XXX"/> 来实现,但是每个交互都有 初始、结束、执行中 三个状态,不同按键排列组合有6种,维护很困难。

研究了下框架下交互传递的逻辑,交互保存在 EvnetConfig中,传递到 DataInteractor 会检擦自己的是否定义对应交互,有的话检擦 stateMachine 是否可以做出响应。

bool mitk::EventStateMachine::HandleEvent(InteractionEvent *event, DataNode *dataNode)
{
  if (!m_IsActive)
    return false;

  if (!FilterEvents(event, dataNode))
  {
    return false;
  }

  // Get the transition that can be executed
  mitk::StateMachineTransition::Pointer transition = GetExecutableTransition(event);

  // check if the current state holds a transition that works with the given event.
  if (transition.IsNotNull())
  {
    // all conditions are fulfilled so we can continue with the actions
    m_CurrentState = transition->GetNextState();

    // iterate over all actions in this transition and execute them
    const ActionVectorType actions = transition->GetActions();
    for (auto it = actions.cbegin(); it != actions.cend(); ++it)
    {
      try
      {
        ExecuteAction(*it, event);
      }
      catch (const std::exception &e)
      {
        MITK_ERROR << "Unhandled excaption caught in ExecuteAction(): " << e.what();
        return false;
      }
      catch (...)
      {
        MITK_ERROR << "Unhandled excaption caught in ExecuteAction()";
        return false;
      }
    }

    return true;
  }
  return false;
}

在需要屏蔽 xml 的自定义的 DataInteractor 类中,重写 FilterEvents 并把对应的 Event 中 Modifiers 置为空即可。

bool NTBoneInteractor3D::FilterEvents(InteractionEvent *interactionEvent, DataNode * /*dataNode*/)
{
    if (interactionEvent->GetSender() == nullptr)
        return false;
    if (interactionEvent->GetSender()->GetMapperID() == BaseRenderer::Standard2D)
        return false;

    int part = -1;
    GetDataNode()->GetIntProperty("current part", part, interactionEvent->GetSender());
    if (part == -1)
    {
        return false;
    }

    if (std::strcmp(interactionEvent->GetNameOfClass(), "MousePressEvent") == 0) {
        auto *mre = dynamic_cast<mitk::MousePressEvent *>(interactionEvent);
        if (nullptr != mre) {
            if (mitk::InteractionEvent::LeftMouseButton == mre->GetEventButton() ||
                mitk::InteractionEvent::MiddleMouseButton == mre->GetEventButton()) {
                mre->SetModifiers(mitk::InteractionEvent::NoKey);
            }
        }
    }

    if (std::strcmp(interactionEvent->GetNameOfClass(), "MouseMoveEvent") == 0) {
        auto *mre = dynamic_cast<mitk::MouseMoveEvent *>(interactionEvent);
        if (nullptr != mre) {
            mre->SetModifiers(mitk::InteractionEvent::NoKey);
        }
    }

    if (std::strcmp(interactionEvent->GetNameOfClass(), "MouseReleaseEvent") == 0) {
        auto *mre = dynamic_cast<mitk::MouseReleaseEvent *>(interactionEvent);
        if (nullptr != mre) {
            if (mitk::InteractionEvent::LeftMouseButton == mre->GetEventButton() ||
                mitk::InteractionEvent::MiddleMouseButton == mre->GetEventButton()) {
                mre->SetButtonStates(mitk::InteractionEvent::NoButton);
                mre->SetModifiers(mitk::InteractionEvent::NoKey);
            }
        }
    }

    return true;
}