VTK/Tutorials/Callbacks

From KitwarePublic
Jump to: navigation, 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:

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

2. Create a vtkCallbackCommand and set its callback to the function you have just created:

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

3. Register the callback that was just created with the object that is observing for the command:

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

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.

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 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:

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

Then in the callback function, you can cast the clientdata to the expected type:

void func ( vtkObject* caller, long unsigned int eventId, void* clientData, void* callData )
{
  vtkSmartPointer<vtkProgrammableFilter> programmableFilter = 
      reinterpret_cast<vtkProgrammableFilter*>(clientData);
}

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.