VTK/Tutorials/Widgets
Introduction
A widget is an object that provides an interface to a complex operation. For example, vtkBoxWidget2 allows you to move a box around a scene. It provides a way to translate the box, rotate the box, and scale the box. Of course this can all be achieved using a vtkCubeSource and a specialized vtkInteractorStyle, but the widget provides all of this in a "canned" way.
Consider referencing the Widgets examples page for more examples.
There are two main components to a widget - the interaction and the representation.
Interaction
The "interaction" is the class named vtk*Widget (for example, vtkBoxWidget2). It contains all of the options for the interaction, as well as the event handling.
Representation
The representation is the object that is drawn and interacted with. The class is named vtk*Representation, where the * is the same * from vtk*Widget.
Usage
To create the widget: <source lang="cpp">
vtkSmartPointer<vtkBoxWidget2> boxWidget = vtkSmartPointer<vtkBoxWidget2>::New(); boxWidget->SetInteractor(renderWindowInteractor);
</source>
Most widgets will create a default representation automatically. If you wish to use several non-defaults, you should probably create the representation manually, and tell the widget to use it: <source lang="cpp">
vtkSmartPointer<vtkBoxRepresentation> boxRepresentation = vtkSmartPointer<vtkBoxRepresentation>::New(); boxWidget->SetRepresentation(boxRepresentation);
</source>
Handling Events
Often you will want to do something in response to the user interacting with the widget. To do this, you should create a subclass of vtkCommand. The Execute function does the work.
<source lang="cpp"> class vtkBoxCallback : public vtkCommand {
public: static vtkBoxCallback *New() { return new vtkBoxCallback; } virtual void Execute(vtkObject *caller, unsigned long, void*) { vtkBoxWidget2 *boxWidget = reinterpret_cast<vtkBoxWidget2*>(caller); //get the actual box coordinates/planes vtkSmartPointer<vtkPolyData> polydata = vtkSmartPointer<vtkPolyData>::New(); static_cast<vtkBoxRepresentation*>(boxWidget->GetRepresentation())->GetPolyData (polydata); //display one of the points, just so we know it's working double p[3]; polydata->GetPoint(0,p); cout << "P: " << p[0] << " " << p[1] << " " << p[2] << endl; } vtkBoxCallback(){}
}; </source>
The Execute function is similar to a vtkCallbackFunction in that the calling object can be obtained by casting "caller" to the appropriate type.
Putting It All Together
To attach this new class to the widget, instantiate the class and call AddObserver on the widget:
<source lang="cpp">
vtkSmartPointer<vtkBoxCallback> boxCallback = vtkSmartPointer<vtkBoxCallback>::New(); boxWidget->AddObserver(vtkCommand::InteractionEvent,boxCallback);
</source>
Enabling the Widget
Widgets seem fussy about the order that things are done. The following order is appropriate: <source lang="cpp">
renderWindow->Render(); renderWindowInteractor->Initialize(); renderWindow->Render();
boxWidget->On(); renderWindowInteractor->Start();
</source>