VTK:交互部件——Widget应用综述

1.交互器样式遇到的问题

交互器样式(vtkInteractorStyleImage)主要是根据不同的键盘、鼠标等消息来控制相机。(vtkCamera)/Actor等相关的参数,从而达到交互的目的。然而,在渲染场景中,这些交互器样式是没有表达实体的。在交互之前用户必须知道哪些键盘消息或者鼠标消息是与哪些事件绑定的,在整个交互过程中,用户“看不到”交互器长什么样子,比如,使用vtkInteractorStyleImage交互样式时,必须知道按键是用于窗宽窗位、相机参数等的重置,鼠标中键可以平移图像,按住鼠标左键不放然后移动鼠标可以调节窗宽窗位等。
在于渲染器中的对象进行交互时,如果可以“看见”交互的样式,这样的交互过程就会更加人性化,比如,要在地图上测量AB两点之间的距离,直观的做法就是:在A点上单击,当松开鼠标后,程序在单击的位置上生成一个端点(该端点可以是圆形、十字形或者其他任何形状),然后移动鼠标至终点,鼠标移动过程中,在A点与鼠标光标的当前位置生成一条线,当鼠标移动至B点时,再点击B点位置,即可显示出AB两点的距离以及生成一条直线。显然,这样的交互方式比交互器样式更加直观、生动。

2、交互部件

VTK提供强大的、可以看得见的交互部件,即Widget。VTK的Widget类主要包括vtk3DWidget和vtkAbstractWidget两个父类。继承关系如下图所示:

在这里插入图片描述

上图中,我们可以看到,vtk3DWidget和vtkAbstractWidget都派生自vtkInteractorObserver,其中,前者主要是在三维渲染场景中生成一个可以用于控制数据的可视化实体,比如点,线段,平面、球体、包围盒等;后者是VTK里实现“交互、表达实体”设计的所有Widget的基类。vtk3DWidget和vtkAbstractWidget的共同基类vtkInteractorObserver里的虚函数Onchar(),主要用于响应交互的开关状态,对应的方法为:

  • vtkInteractorObserver::SetEnable(int);
    vtkInteractorObserver::EnableOn();
    vtkInteractorObserver::EnableOff();
    vtkInteractorObserver::On();
    vtkInteractorObserver::Off();

VTK中Widget的设计是从VTK 5.0版本开始引入的,最初的Widget是从vtk3DWidget派生出来的,从VTK5.1版本开始,VTK中的Widget重新进行设计,主要的设计理念是将Widget的消息处理与几何表达实体分离,但还是保留了vtk3DWidget及其子类。

3、vtkAbstractWidget

vtkAbstractWidget作为基类,只定义了一些公共的API以及实现了“交互/表达实体”分离的设计机制,其中,把从vtkRenderWindowInteractor路由过来的消息(事件)交给vtkAbstractWidget的交互部分处理,而Wideget的“表达实体”则对应一个vtkProp对象或者是vtkWidgetRepresentation的子类。这样做的好处是:事件处理与Widget的表达实体互不干扰,而且可以实现同类Widget使用不同的表达形式,比如,对于测量距离的Widget,可以定义两个十字形式作为Widget的两个端点(也可以定义两个球体来表达)。
此外vtkAbstractWidget类提供了访问vtkWidgetEventTranslator对象的函数,GetEventTranslator(),该对象的作用可以将VTK事件映射为Widget事件(定义在vtkWidgetEvent.h文件中),通过vtkWidgetEventranslator类,我们可以定制与符合自己习惯使用的控制事件相绑定。比如,对于一个测量长度的vtkDistanceWidget,默认的操作是鼠标左键可以确定两个端点的位置,如果对这种操作不习惯,想用鼠标右键实现同样的功能,可以通过代码来实现:
vtkWidgetEventTranslation* eventTranslation = widget->GetEventTranslator(); eventTranslation->SetTranslation( vtkCommand::RightButtonPressEvent, vtkWidgetEvent::Select); eventTranslation->SetTranslation( vtkCommand::RightButtonReleaseEvent, vtkWidgetEvent::Select);

4.VTK事件与Widget事件间的转换关系

上面已经初步分析了如何定制属于自己的Widget交互部件。下面讨论:每一个vtkAbstractWidget子类的内部,都会根据各个子类的功能,使用类vtkWidgetCallbackTranslator,将VTK事件翻译翻译成Widget事件。同时,利用类vtkWidgetCallbackMapper将相应的Widget事件与各个受保护的静态操作函数关联起来。
在这里插入图片描述

例子:

this->CallbackMapper->SetCallbackMethod(
        vtkCommand::LeftButtonPressEvent,
        vtkWidgetEvent::AddPoint,
        this,vtkDistanceWidget::AddPointAction);
this->CallbackMapper->SetCallbackMethod(
        vtkCommand::MouseMoveEvent,
        vtkWidgetEvent::Move,
        this,vtkDistanceWidget::MoveAction);
this->CallbackMapper->SetCallbackMethod(
        vtkCommand::LeftButtonReleaseEvent,
        vtkWidgetEvent::EndSelect,
        this,vtkDistanceWidget::EndSelectAction);
this->CallbackMapper->SetCallbackMethod(
        vtkCommand::LeftButtonPressEvent,
        vtkWidgetEvent::AddPoint,
        this,vtkDistanceWidget::AddPointAction);
this->CallbackMapper->SetCallbackMethod(
        vtkCommand::MouseMoveEvent,
        vtkWidgetEvent::Move,
        this,vtkDistanceWidget::MoveAction);
this->CallbackMapper->SetCallbackMethod(
        vtkCommand::LeftButtonReleaseEvent,
        vtkWidgetEvent::EndSelect,
        this,vtkDistanceWidget::EndSelectAction);

通过上面可知,vtkWidgetCallbackMapper::SetCallbackMathod()将VTK消息与实际的操作函数联系起来,SetCallbackMethod()函数内部则是调用vtkWidgetEventTranslator::SetTranslation方法将VTK事件翻译成Widget事件,这种实现机制有点类似Qt里的信号-槽连接。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

简 。单

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值