【基于MITK开发】交互概念详解及如何实现一个新的数据交互器

(一)交互概念

1.事件处理过程

交互概念本身是独立于任何特定图形用户界面工具包而实现的。
在这里插入图片描述

处理交互事件的对象可被分为两类:
(1)数据交互器(DataInteractor):必须与某个特定数据结点关联,可以操控该数据结点,遵循状态机概念实现。
(2)InteractionEventObserver:不关联任何数据结点,该对象会接收所有用户输
入并仅用于显示,它们绝不应该修改任何数据结点。使用状态机功能是可选的,默认为不使用。

”调度员“Dispatcher:该类接收所有事件,并将它们分发到相关的数据交互实例。
<1> 默认根据数据结点的 layer 属性,降序对数据交互器进行排序;
<2> 然后将事件提供给第一顺序位的数据交互器,后者检查它是否可以处理该
事件。对每个数据交互器都执行此操作,直到遇到第一个能处理该事件为止,此
后将跳过其他剩余的数据交互器并通知所有 InteractionEventObserver。

2.数据交互器

交互概念的核心是,处理一个特定的数据结点的交互事件,可以侦听某些预定义事件并在触发此类事件时执行某些操作。这些都是基于状态机实现的。

(1)状态机

状态机模式:相同的用户交互可以根据当前状态触发不同的动作。 比如,通过鼠标单击来添加线时,前两次单击应该都会是添加一个点,但是第二次单击应另外完成连线的交互,随后的第三次及之后的单击都应被忽略。特定事件动作取决于数据对象的内容和交互状态。状态机就提供了一种很好的方式来建模这种交互。

通过设置多个状态机模式(状态和转换描述),对应不同的触发动作,使得同一数据交换器执行不同的用户交互。每种模式对应一种执行的交互方案。

只需更换状态机模式,就可以将一个数据交互器重复用于不同的任务。这些模式在 XML 文件中描述。

状态机定义:
状态机由四部分组成:
(1)【States】状态,描述交互的当前状态
(2)【transitions】转换,描述从一种状态变为另一种状态所需的事件
(3)【conditions】条件,描述执行转换之前的条件
(4)【actions】动作,在进行转换且该转换的条件已通过时执行

(2)配置

在许多情况下,最好实现独立于特定事件的交互(例如鼠标左键单击),以便可以轻松更改此事件。这是通过配置 InteractionEventHandler 来实现的,这允许在运行时更改行为。

mitk::InteractionEventHandler 类提供一个接口,可以通过加载不同配置文件来轻易修改触发行为的用户输入。

特定事件(specific event)和事件变体(event variant)

  • 特定事件由某个事件类定义,该类确定事件的类别(例如 mitk::MousePressEvent 定义了鼠标按钮类)以及使该事件唯一的参数。
  • 事件变体是分配给特定事件的名称(例如下面定义的两种事件),并且 InteractionEventHandler 侦听该名称。

(二)如何实现一个新的数据交互器

从头创建数据交互器、状态机和配置文件

修改交互器:
需要为实例化的交互对象添加两个xml文件:分别描述了状态机模式触发转换行为的配置。一个数据交互器的行为由这两个xml文件决定。

1.创建配置文件

配置文件中的代码描述了定义的用户输入交互器触发事件(event)之间的映射。每个事件的描述都必须指明事件类(event variant class)和事件变体(event variant name)。事件的参数由属性标签(attribute-tag)设置。

配置文件定义事件的完整示例 <1> 键盘事件:

<config>
 <!-- 描述按下键盘a的事件 -->
 <event_variant class="InteractionKeyEvent" name="StdA"> <!—键盘事件类和键A事件变体-->
 <attribute name="Key" value="A"/> <!—描述事件的属性参数-->
 </event_variant>
 <!-- 描述同时按下键盘b+ctrl+shift的事件 -->
 <event_variant class="InteractionKeyEvent" name="StdB">
 <attribute name="Key" value="B"/>
 <attribute name="Modifiers" value="shift,ctrl"/> <!—修饰键-->
 </event_variant>
</config>

2.创建状态机模式文件

状态机模式文件从状态机定义的state、transition、condition、action四部分入手。
【states】
使用状态标签描述状态,每个状态机必须指定一个启动状态。
【transitions】
Transition 描述所有可能的状态切换,对于建模状态机很重要。它包括描述触发转换的事件(事件类和事件变体)和目标状态(状态机在执行转换后到达的状态)。事件类和事件变体共同确定哪个事件可以触发此转换。比如在“按下鼠标左键”这个事件发生之后,状态由状态 A 转换到了 B。

event class支持事件类的多态性。以通用的方式编写状态机模式。
在这里插入图片描述

在状态机模式中,可以将 InteractionPositionEvent 声明为事件类(event_class),它描述包含位置信息的交互事件,然后在配置文件中给出具体事件的描述。

无论使用什么输入设备(比如鼠标和触控),状态机模式都可以保持不变,并且状态机模式可以为新添加的事件类(比如新增 TouchEvent 事件类)进行配置,只要它们与类层次结构匹配即可。

<!--状态机模式-->
<!—触发状态A到B转换的事件类为InteractionPositionEvent,事件变体为AddPointClick -->
<statemachine>
 <state name="start" startstate="true">
 <transition event_class="InteractionPositionEvent" event_variant="AddPointClick" target="B"/>
 </state>
<state name="B"/>
</statemachine>
<!—配置文件-->
<!—事件类为MousePressEvent,事件变体为AddPointClick -->
<config>
 <event_variant class="MousePressEvent" name="AddPointClick">
 <attribute name="EventButton" value="LeftMouseButton"/>
 <attribute name="Modifiers" value="shift"/>
 </event_variant>
</config>

【actions】
状态发生转换时执行的函数

【conditions】
状态发生转换时执行的函数,用作判定是否执行转换的actions条件

3.集成状态机模式和配置文件

· 现存文件在使用时只需提供文件名即可。
· 自定义模式和配置文件的加载,由于一般存放在其设计所在模块的Resources/Interactions 目录中,将文件从模块位置加载到交互器时,必须将模块作为参数提供。

m_CurrentInteractor = mitk::MyDataInteractor::New();
m_CurrentInteractor->LoadStateMachine("MyStateMachinePattern.xml", us::GetModuleContext()->GetModule());
m_CurrentInteractor->SetEventConfig("MyConfig.xml", us::GetModuleContext()->GetModule());

注意:该文件所在自定义模块需要在应用程序启动时通过 eager 策略激活,否则会找不到该模块定义的内容。

4.创建新的数据交互器

需要从 mitk::DataInteractor 派生自定义数据交互器 mitk::MyInteractor,并遵照以下规则,完成相关 action 和 condition 函数的定义以及这些函数与状态机模式的绑定。

  • 定义actions
  • 定义conditions
  • 绑定actions、conditions与对应函数

新的数据交互器创建完成,调用时按照(3)完成加载即可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值