MITK中State machine和configuration详解和调用顺序

(学习笔记,错误难免,请指正;私人劳动,转载请注明出处)

下面以MITK自带的mitkPointSetDataInteractor.h、mitkPointSetDataInteractor.cpp、PointSet.xml、PointSetConfig.xml为例,解释MITK中的交互原理,以及State machine和configuration的调用顺序。

PointSet.xml:

<statemachine>
    <state name="start" startstate="true">
        <transition event_class="InteractionPositionEvent" event_variant="AddPointClick" target="start">
             <action name="addpoint"/>
        </transition>
        <transition event_class="MouseMoveEvent" event_variant="CheckSelected" target="selected">
            <condition name="isoverpoint"/>
            <action name="selectpoint"/>
        </transition>
        <transition event_class="InteractionKeyEvent" event_variant="Abort" target="start">
          <action name="abort"/>
        </transition>
    </state>
    <state name="selected">
        <transition event_class="MouseMoveEvent" event_variant="CheckSelected" target="start">
            <condition name="isoverpoint" inverted="true"/>
            <action name="unselectAll"/>
        </transition>
        <transition event_class="MousePressEvent" event_variant="DeletePoint" target="start">
            <action name="removePoint"/>
        </transition>
        <transition event_class="MousePressEvent" event_variant="StartMove" target="MovementInitalized">
            <action name="initMove"/>
        </transition>
    </state>
    <state name="MovementInitalized">
      <transition event_class="MouseMoveEvent" event_variant="PointMove" target="MovementInitalized">
          <action name="movePoint"/>
      </transition>
      <transition event_class="MouseReleaseEvent" event_variant="EndMovement" target="selected">
         <action name="finishMovement"/>
      </transition>
    </state>
</statemachine>

PointSetConfig.xml:

<config>
  <!--   Set a maximal number of points here:
  <param name="MaxPoints" value="4"/>
  -->
  <event_variant class="InternalEvent" name="EnoughPoints">
    <attribute name="SignalName" value="MaxNumberOfPoints"/>
  </event_variant>
  <event_variant class="InternalEvent" name="NotEnoughPoints">
    <attribute name="SignalName" value="haslessthen3points"/>
  </event_variant>
  <event_variant class="InteractionKeyEvent" name="Abort">
    <attribute name="Key" value="Escape"/>
  </event_variant>
  <event_variant class="MousePressEvent" name="DeletePoint">
    <attribute name="EventButton" value="LeftMouseButton"/>
    <attribute name="Modifiers" value="alt"/>
  </event_variant>
  <event_variant class="MousePressEvent" name="AddPointClick">
    <attribute name="EventButton" value="LeftMouseButton"/>
    <attribute name="Modifiers" value="shift"/>
  </event_variant>
  <event_variant class="MousePressEvent" name="StartMove">
    <attribute name="EventButton" value="LeftMouseButton"/>
  </event_variant>
  <event_variant class="MouseMoveEvent" name="CheckSelected"/>
  <event_variant class="MouseReleaseEvent" name="EndMovement">
    <attribute name="EventButton" value="LeftMouseButton"/>
  </event_variant>
  <event_variant class="MouseMoveEvent" name="PointMove">
    <attribute name="ButtonState" value="LeftMouseButton"/>
  </event_variant>
</config>

自定义DataInteraction需要继承mitk::DataInteractor。自定义的函数必须通过重写ConnectActionsAndFunctions()函数与statemachine中的行为连接起来。比如mitkPointSetDataInteractor.cpp中:

void mitk::PointSetDataInteractor::ConnectActionsAndFunctions()
{
  // Condition which is evaluated before transition is taken
  // following actions in the statemachine are only executed if it returns TRUE
  CONNECT_CONDITION("isoverpoint", CheckSelection);
  CONNECT_FUNCTION("addpoint", AddPoint);
  CONNECT_FUNCTION("selectpoint", SelectPoint);
  CONNECT_FUNCTION("unselect", UnSelectPointAtPosition);
  CONNECT_FUNCTION("unselectAll", UnSelectAll);
  CONNECT_FUNCTION("initMove", InitMove);
  CONNECT_FUNCTION("movePoint", MovePoint);
  CONNECT_FUNCTION("finishMovement", FinishMove);
  CONNECT_FUNCTION("removePoint", RemovePoint);
}

调用顺序

当一个用户交互事件,如按住shift键单击左键发生时,MousePressEvent,经mitk::Dispatcher分发给对应的mitk::DataInteractor。该mitk::DataInteractor根据随事件传递过来的参数(value=”LeftMouseButton”、value=”shift”)会检查PointSetConfig.xml,结果发现有对应的事件:

  <event_variant class="MousePressEvent" name="AddPointClick">
    <attribute name="EventButton" value="LeftMouseButton"/>
    <attribute name="Modifiers" value="shift"/>
  </event_variant>

这里两个attribute标签即为事件的参数。找到shift+左键对应的event variant,返回event variant的名字“AddPointClick”。接着状态机在PointSet.xml中查找目前状态下是否存在能够被触发的transition,发现有,event_variant=”AddPointClick”。这个transition在start状态里,执行动作“AddPoint”(这个动作对应的函数在上面已经连接好了,为AddPoint()),然后跳到状态”start”。

如果触发的是configuration文件里的CheckSelected,则状态机里对应的是“start”状态里的MouseMoveEvent,检查条件“isoverpoint”是否满足(调用函数CheckSelection()),如果满足,执行行为”selectpoint”(调用函数SelectPoint()),然后根据target=”selected”跳到“selected”状态。这时如果configuration文件里的CheckSelected再被触发,则对应的transition是“selected”状态里的:

 <transition event_class="MouseMoveEvent" event_variant="CheckSelected" target="start">
            <condition name="isoverpoint" inverted="true"/>
            <action name="unselectAll"/>

我们看到,这时应该执行的行为就变为”unselectAll”了。

上行代码中 inverted=”true”是什么意思?

时间: 2024-11-03 22:09:01

MITK中State machine和configuration详解和调用顺序的相关文章

【转】Android中measure过程、WRAP_CONTENT详解以及xml布局文件解析流程浅析(下)

转载请注明出处:http://blog.csdn.net/qinjuning 上篇文章<<Android中measure过程.WRAP_CONTENT详解以及xml布局文件解析流程浅析(上)>>中,我们 了解了View树的转换过程以及如何设置View的LayoutParams的.本文继续沿着既定轨迹继续未完成的job. 主要知识点如下:                 1.MeasureSpc类说明                 2.measure过程详解(揭秘其细节);   

oc中字典的实现方法详解

一:字典的基本概念 Foundation中的字典(NSDictionary,NSMutableDictionary)是由键-值对组成的数据集合.正如,我们在字典里查找单词的定义一样. 通过key(键),查找的对应的value(值),key通常是字符串对象,也可以是其他任意类型对象.在一个字典对象中,key的值必须是唯一的. 此外,字典对象的键和值不可以为空(nil),如果需要在字典中加入一个空值,可以加入NSNull对象 二:不可变字典-NSDictionary 1:初始化(以一个元素和多个元素

JDK中的Timer和TimerTask详解

目录结构: Timer和TimerTask 一个Timer调度的例子 如何终止Timer线程 关于cancle方式终止线程 反复执行一个任务 schedule VS. scheduleAtFixedRate 一些注意点 1. Timer和TimerTask Timer是jdk中提供的一个定时器工具,使用的时候会在主线程之外起一个单独的线程执行指定的计划任务,可以指定执行一次或者反复执行多次. TimerTask是一个实现了Runnable接口的抽象类,代表一个可以被Timer执行的任务. 2.

Android总结篇系列:Activity中几个主要函数详解

专注Android领域开发. 仰望星空,同时需要脚踏实地. ——好记性不如烂博客 Android总结篇系列:Activity中几个主要函数详解 Activity作为Android系统中四大基本组件之一,包含大量的与其他的各大组件.intent.widget以及系统各项服务等之间的交互的函数.在此,本文主要选取实际项目开发中常用的,但完全理解又需要有一定深入了解的几个函数进行讲解,后续本文会根据需要不断更新. 1. startActivityForResult / onActivityResult

【转载】lucene中Field.Index,Field.Store详解

lucene在doc.add(new Field("content",curArt.getContent(),Field.Store.NO,Field.Index.TOKENIZED)); Field有两个属性可选:存储和索引. 通过存储属性你可以控制是否对这个Field进行存储: 通过索引属性你可以控制是否对该Field进行索引. 事实上对这两个属性的正确组合很重要. Field.Index Field.Store 说明 TOKENIZED(分词) YES 被分词索引且存储 TOKE

【Unity编程】Unity中关于四元数的API详解

Unity中关于四元数的API详解 Quaternion类 Quaternion(四元数)用于计算Unity旋转.它们计算紧凑高效,不受万向节锁的困扰,并且可以很方便快速地进行球面插值. Unity内部使用四元数来表示所有的旋转. Quaternion是基于复数,并不容易直观地理解. 不过你几乎不需要访问或修改单个四元数参数(x,y,z,w); 大多数情况下,你只需要获取和使用现有的旋转(例如来自"Transform"),或者用四元数来构造新的旋转(例如,在两次旋转之间平滑插入). 大

Oracle中常用的to_Char用法详解

Oracle中常用的to_Char用法详解(有FMT的详细列表) The following are number examples for the to_char function. to_char(1210.73, '9999.9') would return '1210.7' to_char(1210.73, '9,999.99') would return '1,210.73' to_char(1210.73, '$9,999.00') would return '$1,210.73'

第52讲:Scala中路径依赖代码实战详解

<DT大数据梦工厂>大数据实战视频"Scala深入浅出实战经典"视频.音频和PPT下载!第52讲:Scala中路径依赖代码实战详解百度云:http://pan.baidu.com/s/1gdES4hX360云盘:http://yunpan.cn/ccHXX2Wkrrrt4 访问密码 c489腾讯微云:http://url.cn/VV5kx5 记录: Scala中内部类的路径依赖非常适合现在互联网看待事物所属关系,组织关系. 根据依赖的外部实例的不同,内部类类型会有所不同.由

SVN中tag branch trunk用法详解

SVN中tag branch trunk用法详解 2010-05-24 18:32 佚名 字号:T | T 本文向大家简单介绍一下SVN中tag branch trunk用法,SVN中tag branch trunk都属于SVN的子命令,那么他们是如何使用的呢,本文就给大家一一讲解. AD:干货来了,不要等!WOT2015 北京站演讲PPT开放下载! 本节主要讲解一下SVN中tag branch trunk的用法,在SVN中Branch/tag在一个功能选项中,在使用中也往往产生混淆.这里就向大