VTK修炼之道73:交互部件_Widget应用综述
来源:互联网 发布:马来西亚旅游业数据 编辑:程序博客网 时间:2024/05/17 05:10
1.交互器样式遇到的难题
交互器样式(如vtkInteractorStyleImage)主要是根据不同的键盘、鼠标等消息来控制相机(vtkCamera)/Actor等相关参数,从而达到了交互的目的!然而,在渲染场景中,这些交互器样式是没有表达实体的。也就是说,在交互之前,我们(用户)必须知道那些键盘消息或者鼠标消息是与哪些事件绑定的,在整个交互过程中,用户“看不到”交互器样式长什么样子,比如,使用vtkInteractorStyleImage交互器样式时,必须知道按键<R>是用于窗宽窗位、相机参数等的重置,鼠标中键可以平移图像,按住鼠标左键不放然后移动鼠标可以调节窗宽窗位等。在与渲染场景中的对象进行交互时,如果可以“看得见”交互的样式,这样的交互过程就会更加的人性化,比如,要在地图上测量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及其子类。2.1 vtkAbstractWidget
vtkAbstractWidget作为基类,只定义一些公共的API以及实现了“交互/表达实体”分离的设计机制,其中,把从vtkRenderWindowInteractor路由过来的消息(事件)交给vtkAbstractWidget的“交互”部分处理,而Widget的“表达实体”则对应一个vtkProp对象(或者是vtkWidgetRepresentation的子类)。这样做的好处是:事件处理与Widget的表达实体互不干扰,而且可以实现同类Widget使用不同的表达形式,比如,对于测量距离的Widget,可以定义两个十字形作为Widget的两个端点(也可以定义两个球体来表达)。此外,vtkAbstractWidget类提供了访问vtkWidgetEventTranslator对象的函数,GetEventTranslator(),该对象的作用可以将VTK事件映射为Widget事件(定义在vtkWidgetEvent.h文件中),通过vtkWidgetEventTranslator类,我们可以定制与符合自己习惯使用的控制事件相绑定。比如,对于一个测量长度的vtkDistanceWidget,默认的操作是鼠标左键可以确定两个端点的位置,如果对这种操作不习惯,想用鼠标右键实现同样的功能,可以通过代码来实现:
- vtkWidgetEventTranslation* eventTranslation = widget->GetEventTranslator();
- eventTranslation->SetTranslation(
- vtkCommand::RightButtonPressEvent,
- vtkWidgetEvent::Select);
- eventTranslation->SetTranslation(
- vtkCommand::RightButtonReleaseEvent,
- vtkWidgetEvent::Select);
2.2 VTK事件与Widget事件间的转换关系
上面已经初步分析了何如定制属于自己的Widget交互部件。下面进一步讨论:每个vtkAbstractWidget子类的内部,都会根据各个子类的功能,使用类vtkWidgetEventTranslator,将VTK事件爱你翻译成Widget事件。同时,利用类vtkWidgetCallbackMapper将相应的Widget事件与各个受保护的静态操作函数关联起来,具体关系如下图所示:以vtkDistanceWidget为例,在该类的构造函数中,有如下代码:上述代码中的CallbackMapper即为vtkWidgetCallbackMapper类型,SetCallbackMethod()函数代码如下:
- 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);
- void vtkWidgetCallbackMapper::SetCallbackMethod(
- unsigned long VTKEvent,
- unsigned long widgetEvent,
- vtkAbstractWidget* w,
- CallbackType f)
- {
- this->EventTranslator->SetTranslation(VTKEvent, widgetEvent);
- this->SetCallbackMethod(widgetEvent,w,f);
- }
2.3 小结
通过上面可知,vtkWidgetCallbackMapper::SetCallbackMathod()将VTK消息与实际的操作函数联系起来,SetCallbackMethod()函数内部则是调用vtkWidgetEventTranslator::SetTranslation方法将VTK事件翻译成Widget事件,这种实现机制有点类似Qt里的信号-槽连接。
3.参看资料
1.《C++ primer》
2.《The VTK User’s Guide – 11thEdition》
3. 张晓东, 罗火灵. VTK图形图像开发进阶[M]. 机械工业出版社, 2015.
阅读全文
0 0
- VTK修炼之道73:交互部件_Widget应用综述
- VTK修炼之道73:交互部件_Widget应用综述
- VTK修炼之道74:交互部件_Widget的创建
- VTK修炼之道75:交互部件_测量类Widget的应用
- VTK修炼之道76:交互部件_标注类Widget的应用
- VTK修炼之道77:交互部件_分割/配准类Widget与其他Widget
- VTK修炼之道72:交互与Widget_交互器样式
- VTK修炼之道71:交互与Widget_观察者/命令模式
- VTK修炼之道78:交互与拾取_点拾取
- VTK修炼之道79:交互与拾取_单位拾取
- VTK修炼之道1_初识VTK
- 99_widget,窗口小部件
- VTK交互之vtkCommand
- VTK交互之Widget
- VTK交互之拾取
- VTK交互之交互样式
- VTK修炼之道2_VTK体系结构1
- VTK修炼之道3_VTK体系结构2
- protoc生成 caffe.pb.cc和caffe.pb.hpp
- python实例pyspark以及python中文显示
- JavaScript DOM 高级程序设计 第1章 遵循最佳实践 摘记
- uva993 Product of digits
- Java基础知识_毕向东_Java基础视频教程笔记(13)
- VTK修炼之道73:交互部件_Widget应用综述
- C# 委托事件简单示例
- VSCode调教以及快捷键记录提高开发效率
- 最大子串和
- python:'return' outside function 错误
- 《第二篇》关于健康
- 用JS实现带cookies保存记录的换肤功能
- notion 建立项目知识
- 事件与事件流技术盘点