简介:
回调函数就是命令/观察者模式中的观察者。VTK对象状态发生变化时,它就会发出一个命令通知所有观察家该事件。
为了捕获这个事件,你需要做下面几件事:
1\. 声明一个如下形式的函数:
**void** func(vtkObject*, **unsigned** **long** eid, **void*** clientdata, **void** *calldata)
2\. 创建一个vtkCallbackCommand对象,并将其回调函数设置为你自己创建的函数:
vtkSmartPointer<vtkCallbackCommand> keypressCallback =
vtkSmartPointer<vtkCallbackCommand>::New();
keypressCallback->SetCallback ( func );
或者
2\. 创建一个vtkCallbackCommand并重写execute函数:
virtual void Execute(vtkObject *caller, unsigned long, void*)
它会在创建CallbackCommand对象后自动当成callback被执行
vtkSmartPointer<vtkCallbackCommand> keypressCallback =
vtkSmartPointer<vtkCallbackCommand>::New();
3\. 注册callback,监听命令
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderWindowInteractor->SetRenderWindow(renderWindow);renderWindowInteractor->AddObserver ( vtkCommand::KeyPressEvent, keypressCallback );
在这个例子中,vtkRenderWindowInteractor用来监听KeyPressEvent事件。
**caller**
vtkObject对象caller是观察者的指针。在例子中,因为我们是绑定vtkCallbackCommand在vtkRenderWindowInteractor对象上,所以我们可以强制类型转换caller到vtkRenderWindowInteractor类型。
**void** KeypressCallbackFunction ( vtkObject* caller, **long** **unsigned** **int** eventId, **void*** clientData, **void*** callData )
{
cout << "Keypress callback" <<endl;vtkRenderWindowInteractor *iren =
**static_cast**<vtkRenderWindowInteractor*>(caller);
cout << "Pressed: " << iren->GetKeySym() << endl;
}
**clientdata**
clientdata提供了一种方法来提供对数据的访问,将必要的回调函数。你可以使用vtkCallbackCommand函数的SetClientData方法设置该数据。假如,您想要访问回调函数的vtkProgrammableFilter实例,你可以这么做:
vtkSmartPointer<vtkProgrammableFilter> filter =
vtkSmartPointer<vtkProgrammableFilter>::New();vtkSmartPointer<vtkCallbackCommand> timerCallback =
vtkSmartPointer<vtkCallbackCommand>::New();
timerCallback->SetCallback ( func );
timerCallback->SetClientData(filter);
然后再回调函数中,你可以这样使用该数据:
**void** func ( vtkObject* caller, **long** **unsigned** **int** eventId, **void*** clientData, **void*** callData )
{
vtkSmartPointer<vtkProgrammableFilter> programmableFilter =
**reinterpret_cast**<vtkProgrammableFilter*>(clientData);
}
完整范例:
#**include** <vtkPolyDataMapper.h>
#**include** <vtkActor.h>
#**include** <vtkSmartPointer.h>
#**include** <vtkRenderWindow.h>
#**include** <vtkRenderer.h>
#**include** <vtkRenderWindowInteractor.h>
#**include** <vtkPolyData.h>
#**include** <vtkSphereSource.h>
#**include** <vtkCallbackCommand.h>
#**include** <vtkCommand.h>**static** **void** KeypressCallbackFunction ( vtkObject* caller, **long** **unsigned** **int** eventId,
**void*** clientData, **void*** callData );
**int** main(**int**, **char** *[])
{
// Create a sphere
vtkSmartPointer<vtkSphereSource> sphereSource =
vtkSmartPointer<vtkSphereSource>::New();
sphereSource->SetCenter(0.0, 0.0, 0.0);
sphereSource->SetRadius(5.0);
sphereSource->Update();
vtkSmartPointer<vtkPolyDataMapper> mapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(sphereSource->GetOutputPort());
// Create an actor
vtkSmartPointer<vtkActor> actor =
vtkSmartPointer<vtkActor>::New();
actor->SetMapper(mapper);
// A renderer and render window
vtkSmartPointer<vtkRenderer> renderer =
vtkSmartPointer<vtkRenderer>::New();
vtkSmartPointer<vtkRenderWindow> renderWindow =
vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->AddRenderer(renderer);
// An interactor
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderWindowInteractor->SetRenderWindow(renderWindow);
vtkSmartPointer<vtkCallbackCommand> keypressCallback =
vtkSmartPointer<vtkCallbackCommand>::New();
// Allow the observer to access the sphereSource
**keypressCallback->SetClientData(sphereSource);//设置clientdata对象**
** keypressCallback->SetCallback(KeypressCallbackFunction );//将回调命令与callback函数绑定**
**renderWindowInteractor->AddObserver(vtkCommand::KeyPressEvent, keypressCallback);//监听keypress事件,绑定回调命令**
renderer->AddActor(actor);
renderer->SetBackground(1,1,1); // Background color white
renderWindow->Render();
renderWindowInteractor->Start();
**return** EXIT_SUCCESS;
}
**void** KeypressCallbackFunction(vtkObject* caller, **long** **unsigned** **int** vtkNotUsed(eventId), **void*** clientData, **void*** vtkNotUsed(callData) )
{
// Prove that we can access the sphere source
** vtkSphereSource* sphereSource =
static_cast<vtkSphereSource*>(clientData);//强制类型转换为原来的对象**
std::cout << "Radius is " << sphereSource->GetRadius() << std::endl;
}
**calldata**
calldata是通过callback传递的数据。例如,当ProgressEvent事件被发送时,进程值可以作为calldata被一同发送。
完整范例:在这里例子中,我们创建一个自定义的VTK过滤器来调用我们绑定的带有calldata值的事件。我们使用一个定制的计时器来更新过滤器以便事件可以自动重复触发。更新过程为vtkMyTestFilter更新-> vtkCallbackCommand-> CallbackFunction
#**include** "vtkObjectFactory.h"
#**include** "vtkCommand.h"
#**include** "vtkCallbackCommand.h"
#**include** "vtkStreamingDemandDrivenPipeline.h"
#**include** "vtkInformationVector.h"
#**include** "vtkInformation.h"
#**include** "vtkDataObject.h"
#**include** "vtkSmartPointer.h"
#**include** "vtkAppendPolyData.h"
#**include** "vtkSphereSource.h"
#**include** "vtkPolyDataAlgorithm.h"
#**include** "vtkRenderer.h"
#**include** "vtkRenderWindow.h"
#**include** "vtkRenderWindowInteractor.h"
**class** vtkMyTestFilter : **public** vtkPolyDataAlgorithm
{
**public**:
vtkTypeMacro(vtkMyTestFilter,vtkPolyDataAlgorithm);
**static** vtkMyTestFilter *New();
**int** RefreshEvent;
**protected**:
vtkMyTestFilter()
{
**this**->SetNumberOfInputPorts(0);
**this**->RefreshEvent = vtkCommand::UserEvent + 1;
**this**->Counter = 0;
}
**int** RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *)
{
**this**->InvokeEvent(**this**->RefreshEvent, &**this**->Counter);
**this**->Counter++;
**return** 1;
}
**private**:
vtkMyTestFilter(**const** vtkMyTestFilter&); // Not implemented.
**void** **operator**=(**const** vtkMyTestFilter&); // Not implemented.
**unsigned** **int** Counter;
};
vtkStandardNewMacro(vtkMyTestFilter);
**static** **void** CallbackFunction(vtkObject* caller,
**long** **unsigned** **int** eventId,
**void*** clientData,
**void*** callData );
**class** vtkTimerCallback : **public** vtkCommand
{
**public**:
**static** vtkTimerCallback *New()
{
vtkTimerCallback *cb = **new** vtkTimerCallback;
**return** cb;
}
**virtual** **void** Execute(vtkObject *vtkNotUsed(caller),
**unsigned** **long** vtkNotUsed(eventId),
**void** *vtkNotUsed(callData))
{
TestFilter->Modified();
TestFilter->Update();
}
vtkMyTestFilter* TestFilter;
};
**int** main(**int**, **char** *[])
{
// Create a renderer, render window, and interactor
vtkSmartPointer<vtkRenderer> renderer =
vtkSmartPointer<vtkRenderer>::New();
vtkSmartPointer<vtkRenderWindow> renderWindow =
vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->AddRenderer(renderer);
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderWindowInteractor->SetRenderWindow(renderWindow);
vtkSmartPointer<vtkMyTestFilter> testFilter =
vtkSmartPointer<vtkMyTestFilter>::New();
vtkSmartPointer<vtkCallbackCommand> callback =
vtkSmartPointer<vtkCallbackCommand>::New();
**callback->SetCallback(CallbackFunction );**
**testFilter->AddObserver(testFilter->RefreshEvent, callback);//将callback函数绑定testFilter的更新事件**
testFilter->Update();
renderWindow->Render();
renderWindowInteractor->Initialize();
// Sign up to receive TimerEvent
vtkSmartPointer<vtkTimerCallback> timerCallback =
vtkSmartPointer<vtkTimerCallback>::New();
timerCallback->TestFilter = testFilter;
renderWindowInteractor->AddObserver(vtkCommand::TimerEvent, timerCallback);
renderWindowInteractor->CreateRepeatingTimer(100);
renderWindowInteractor->Start();
**return** EXIT_SUCCESS;
}
**void** CallbackFunction(vtkObject* vtkNotUsed(caller),
**long** **unsigned** **int** vtkNotUsed(eventId),
**void*** vtkNotUsed(clientData),
**void*** callData )
{
**unsigned** **int*** callDataCasted = **reinterpret_cast**<**unsigned** **int***>(callData);
std::cout << *callDataCasted << std::endl;
}