VTK/Tutorials/Widgets

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

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:

  vtkSmartPointer<vtkBoxWidget2> boxWidget = 
    vtkSmartPointer<vtkBoxWidget2>::New();
  boxWidget->SetInteractor(renderWindowInteractor);

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:

  
  vtkSmartPointer<vtkBoxRepresentation> boxRepresentation = 
      vtkSmartPointer<vtkBoxRepresentation>::New();
  boxWidget->SetRepresentation(boxRepresentation);

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.

  
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(){}
    
};

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:

  
  vtkSmartPointer<vtkBoxCallback> boxCallback = 
      vtkSmartPointer<vtkBoxCallback>::New();
 
  boxWidget->AddObserver(vtkCommand::InteractionEvent,boxCallback);

Enabling the Widget

Widgets seem fussy about the order that things are done. The following order is appropriate:

  
  renderWindow->Render();
  renderWindowInteractor->Initialize();
  renderWindow->Render();

  boxWidget->On();
  
  renderWindowInteractor->Start();