vtkAbstractWidget has its mechanism to handle interactive events.
Here is a simple demo indicates the differences between the responses of widget and vtkInteractorStyleTrackballCamera.
Example Code:
int main()
{
vtkSmartPointer<vtkConeSource> cone =
vtkSmartPointer<vtkConeSource>::New();
cone->Update();
vtkSmartPointer<vtkPolyDataMapper> coneMapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
coneMapper->SetInputData( cone->GetOutput() );
coneMapper->Update();
vtkSmartPointer<vtkActor> coneActor =
vtkSmartPointer<vtkActor>::New();
coneActor->SetMapper( coneMapper );
vtkSmartPointer<vtkPointHandleRepresentation3D> handleRep =
vtkSmartPointer<vtkPointHandleRemartPointer<vtkPointHandleRepresentation3D>::New();
handleRep->SetPlaceFactor( 2.5 );
handleRep->PlaceWidget( coneActor->GetBounds() );
handleRep->SetHandleSize( 150 );
vtkSmartPointer<vtkRenderer> renderer =
vtkSmartPointer<vtkRenderer>::New();
renderer->AddActor( coneActor );
renderer->SetBackground( 0, 0, 0 );
vtkSmartPointer<vtkRenderWindow> renderWindow =
vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->AddRenderer( renderer );
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderWindowInteractor->SetRenderWindow( renderWindow );
vtkSmartPointer<vtkHandleWidget> handleWidget =
vtkSmartPointer<vtkHandleWidget>::New();
handleWidget->SetInteractor( renderWindowInteractor );
handleWidget->SetRepresentation( handleRep );
handleWidget->EnabledOn();
renderer->ResetCamera();
renderWindow->Render();
teractor->Start();
return 0;
}
I checked handleWidget’s current renderer with the following code.
qDebug( "handleWidget's render: %p, renderer: %p\n",
handleWidget->GetCurrentRenderer(), renderer.Get() );
Then I found that it’s one renderer to render cone and widget.
So they have the same camera to display the 3D model. But why would the handle widget keep same size but cone zoomed in or out when scroll the mouse?
The difference is caused by vtkAbstractWidget internal vtkWidgetCallbackMapper member object which maps widget events into static class methods.
These static methods redefine widget’s responses to users actions.
// vtkHandleWidget.h
// These are the callbacks for this widget
static void GenericAction(vtkHandleWidget*);
static void SelectAction(vtkAbstractWidget*);
static void EndSelectAction(vtkAbstractWidget*);
static void TranslateAction(vtkAbstractWidget*);
...
// vtkHandleWidget.cxx
vtkHandleWidget::vtkHandleWidget()
{
// Set the initial state
this->WidgetState = vtkHandleWidget::Start;
// Okay, define the events for this widget
this->CallbackMapper->SetCallbackMethod(vtkCommand::LeftButtonPressEvent,
vtkWidgetEvent::Select,
this, vtkHandleWidget::SelectAction);
this->CallbackMapper->SetCallbackMethod(vtkCommand::LeftButtonReleaseEvent,
vtkWidgetEvent::EndSelect,
this, vtkHandleWidget::EndSelectAction);
this->CallbackMapper->SetCallbackMethod(vtkCommand::MiddleButtonPressEvent,
vtkWidgetEvent::Translate,
this, vtkHandleWidget::TranslateAction);
this->CallbackMapper->SetCallbackMethod(vtkCommand::MiddleButtonReleaseEvent,
vtkWidgetEvent::EndTranslate,
this, vtkHandleWidget::EndSelectAction);
...
The traditional UI event response for user operations such as rotating and moving are defined in vtkInteractorStyle group class.
For example, vtkInteractorStyleTrackballCamera has a few functions that are resposible to users’ operations.
class VTKINTERACTIONSTYLE_EXPORT vtkInteractorStyleTrackballCamera : public vtkInteractorStyle
{
public:
//...
void OnMouseMove() override;
void OnLeftButtonDown() override;
void OnLeftButtonUp() override;
void OnMiddleButtonDown() override;
void OnMiddleButtonUp() override;
void OnRightButtonDown() override;
void OnRightButtonUp() override;
void OnMouseWheelForward() override;
void OnMouseWheelBackward() override;