VTK/Tutorials/Callbacks

From KitwarePublic
< VTK‎ | Tutorials
Jump to navigationJump to search

Introduction

A callback function is the "observer" in the "command/observer" design pattern. That is, there are times when VTK will know that something has happened and it will send out a command notifying all observers of the event.

To catch these commands, you must do three things:

1. Create a function with this signature: <source lang="cpp">

void func(vtkObject*, unsigned long eid, void* clientdata, void *calldata)

</source>

2. Create a vtkCallbackCommand and set its callback to the function you have just created: <source lang="cpp">

 vtkSmartPointer<vtkCallbackCommand> keypressCallback = 
     vtkSmartPointer<vtkCallbackCommand>::New();
 keypressCallback->SetCallback ( func );

</source>

OR

2. Create a vtkCallbackCommand and reimplement <source lang="cpp"> virtual void Execute(vtkObject *caller, unsigned long, void*) </source> It will then automatically be the callback used when creating the CallbackCommand object with <source lang="cpp">

 vtkSmartPointer<vtkCallbackCommand> keypressCallback = 
     vtkSmartPointer<vtkCallbackCommand>::New();

</source>

3. Register the callback that was just created with the object that is observing for the command: <source lang="cpp">

vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =

     vtkSmartPointer<vtkRenderWindowInteractor>::New();
 renderWindowInteractor->SetRenderWindow(renderWindow);
 renderWindowInteractor->AddObserver ( vtkCommand::KeyPressEvent, keypressCallback );

</source>

In this example, the vtkRenderWindowInteractor is listening for the command KeyPressEvent. A complete list of commands that are available can be found here.

Writing the Callback Function

caller

The vtkObject "caller" is a pointer to the observer. In this example, since we attached the vtkCallbackCommand to a vtkRenderWindowInteractor, we can successfully cast "caller" to a vtkRenderWindowInteractor.

<source lang="cpp"> 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;

}

</source>

clientdata

clientdata provides a way to provide access to data that will be necessary in the callback function. You can set this data using the SetClientData function of vtkCallbackCommand. For example, if you want to have access to an instance of a vtkProgrammableFilter in the callback function, you can do:

<source lang="cpp">

 vtkSmartPointer<vtkProgrammableFilter> filter = 
     vtkSmartPointer<vtkProgrammableFilter>::New();
 vtkSmartPointer<vtkCallbackCommand> timerCallback = 
     vtkSmartPointer<vtkCallbackCommand>::New();
 timerCallback->SetCallback ( func );
 timerCallback->SetClientData(filter);

</source>

Then in the callback function, you can cast the clientdata to the expected type: <source lang="cpp"> void func ( vtkObject* caller, long unsigned int eventId, void* clientData, void* callData ) {

 vtkSmartPointer<vtkProgrammableFilter> programmableFilter = 
     reinterpret_cast<vtkProgrammableFilter*>(clientData);

} </source>

A full example is here.

calldata

calldata is data that may be sent with the callback. For example, when the ProgressEvent event is sent, it sends the progress value as calldata. A full example is here.