1 unsigned long AddObserver(unsigned long event, vtkCommand* , float priority = 0.0f);
2 void RemoveObserver(unsigned long tag);
virtual void Execute(vtkObject* caller, unsigned long eventId, void* callData) = 0;
当观察者检测到event消息时,会响应该函数来执行用户设定的操作。
vtkCommand只是定义了一个接口,我们必须生成一个vtkCommand子类,并覆盖Execute()函数实现具体的功能。
第一种方式是生成vtkCommand子类,并覆盖Execute()函数,在该函数中实现相应的功能。virtual void Execute(vtkObject* caller, unsigned long eventId, void* callData) = 0;该函数有三个参数,caller为触发消息对象;eventId为消息Id;callData为消息触发时需要传递的数据。
第二种方式是使用VTKCallbackCommand类。该类继承vtkCommand,其内部虽然覆盖了Execute()函数,但其实现是调用了一个内部函数,我们必须要自己定义这个函数。该函数为: void (*Callback) (vtkObject* , unsigned long , void* , void* );我们需要实现一个相同形式的回调函数,并通过SetCallback()函数来设置回调函数的指针:void SetCallback( void(*f) (vtkObject* caller, unsigned long eid, void* clientdata, void* calldata) );
当我们定义了Callback()函数后,通过SetCallback()函数为VTKCallbackCommand设置回调函数。
通过对比Callback()函数的形式与Execute()函数,我们可以发现函数参数数目有所不同。不同之处在于Callback()函数多了一个clientdata参数。这是为回调函数中使用其他对象留的一个接口。
2.2 VTK中消息触发
vtkObject中定义了触发消息的函数:
int InvokeEvent(unsigned long event, void* callData);
event为触发的消息ID,callData为触发消息后传递的数据。当使用一个对象的InvokeEvent()来触发一个消息后,对象则遍历其内部添加的vtkObserver对象,一旦发现与某个vtkObserver对象的消息ID一致,就会执行该vtkObserver对象中的vtkCommand回调函数执行相应得操作,将callData传递到vtkCommand对象的Excute()函数中,vtkObject及其子类都可以添加一个或者多个vtkObserver对象,从而实现对不同的消息做出不同的响应。
2.3 观察者监听消息实例
1 #include <vtkVersion.h>
2 #include <vtkSmartPointer.h>
3 #include "vtkTestFilter.h"
4 #include <vtkCallbackCommand.h>
5 #include <vtkCommand.h>
6
7 void CallbackFunction(vtkObject* caller,
8 long unsigned int eventId,
9 void* clientData, void* callData )
10 {
11 int* callDataCasted = reinterpret_cast<int*>(callData);
12 std::cout << *callDataCasted << std::endl;
13 }
14
15 int main()
16 {
17 vtkSmartPointer<vtkTestFilter> filter =
18 vtkSmartPointer<vtkTestFilter>::New();
19
20 vtkSmartPointer<vtkCallbackCommand> callback =
21 vtkSmartPointer<vtkCallbackCommand>::New();
22 callback->SetCallback(CallbackFunction );
23
24 filter->AddObserver(MyEvent, callback);
25 filter->Update();
26
27 system("pause");
28 return EXIT_SUCCESS;
29 }