所谓交互器样式,就是你设置了交互器,然后它里面会有各种默认的或者你自己定义的交互方式,比如你可以设置滚轮来将图片放大或者缩小。或者你可以设置鼠标点击移动来改变摄像机的视角,从而看到物体的不同面。
VTK程序需要首先捕获你的事件,然后根据你触发的事件,结合交互器的样式,来执行相应的函数。
之前在学习的时候我看了很多例子,模仿着写了很多自定义的样式,但是对里面的机制有些难以理解。后来我看了《VTK图形图像开发进阶》张晓东,罗火灵编著的书,个人觉得这本书针对这种交互器的执行内容比较浅显,但是用来了解交互器样式已经很足够了,毕竟我们的主要目标是为了使用,而不是完全理解里面的机制。
但是这里并不打算介绍太多机制,因为用处其实也不是很大,这一节就简单介绍一点内容,然后下一节开始自己写相应的交互器样式。
首先我们来介绍vtkRenderWindowInteractor,即渲染窗口交互器,用来提供鼠标按键等事件的交互机制,然后将事件的消息传送给vtkInteractorObserver或者其子类。
我们先使用一个程序:
#include<vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2)
VTK_MODULE_INIT(vtkInteractionStyle);
VTK_MODULE_INIT(vtkRenderingFreeType);
VTK_MODULE_INIT(vtkRenderingVolumeOpenGL2);
#include <iostream>
using std::cout;
using std::endl;
#include <vtkSmartPointer.h>
#include <vtkPNGReader.h>
#include <vtkImageViewer2.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkCallbackCommand.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkInteractorStyleImage.h>
void MywCallbackFunc(vtkObject*, unsigned long eid, void* clientdata, void *calldata)
{
cout << "aaaaaaa "<<endl;
}
int main(int argc, char* argv[])
{
vtkSmartPointer<vtkPNGReader> reader = vtkSmartPointer<vtkPNGReader>::New();
reader->SetFileName("timg.png");
vtkSmartPointer<vtkImageViewer2> viewer = vtkSmartPointer<vtkImageViewer2>::New();
viewer->SetInputConnection(reader->GetOutputPort());
vtkSmartPointer<vtkRenderWindowInteractor> interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
viewer->SetupInteractor(interactor);
viewer->Render();
viewer->GetRenderer()->SetBackground(1.0, 1.0, 1.0);
viewer->SetSize(640, 480);
viewer->GetRenderWindow()->SetWindowName("ai jiao sha jiao sha");
vtkSmartPointer<vtkCallbackCommand> mouseCallback =
vtkSmartPointer<vtkCallbackCommand>::New();
mouseCallback->SetCallback(MywCallbackFunc);
interactor->SetRenderWindow(viewer->GetRenderWindow());
interactor->AddObserver(vtkCommand::LeftButtonPressEvent, mouseCallback);
vtkSmartPointer<vtkInteractorStyleImage> style =
vtkSmartPointer<vtkInteractorStyleImage>::New();
interactor->SetInteractorStyle(style);
interactor->Initialize();
interactor->Start();
return EXIT_SUCCESS;
}
vtkRenderWindowInteractor在系统上创建与windows相关的子类对象(比如windows系统上与windows相关的子类,linux上与linux相关的子类),然后使用Start函数不断地从消息队列中获取消息,把获得的消息分发给回调函数,回调函数根据不同的消息来调用不同的响应消息函数,在每个响应函数通过vtkObject::InvokeEvent将平台相关的消息翻译为vtk事件,例如我们上面写的事件,会被翻译成类似onMousePressEvent这样的事件。
vtkInteractorStyle:
vtkObject::InvokeEvent()将各个VTK事件分发到不同的观察者中,观察者调用回调函数vtkInteractorStyle::ProcessEvents()处理不同的VTK事件,再将这些事件分发至vtkInteractorStyle的消息响应函数中,然后完成整个消息的传递。