Unable to capture clicked event from vtkQWidgetWidget

I’m unable to capture any event from vtkQWidgetWidget to Qt Widgets. Here is the code

class CustomInteractorStyle : public vtkInteractorStyleTrackballCamera
{
public:
static CustomInteractorStyle* New()
{
return new CustomInteractorStyle(); // Manual implementation of the New() method
}

vtkTypeMacro(CustomInteractorStyle, vtkInteractorStyleTrackballCamera);

QWidget* qtWidget;  // Pointer to the Qt widget to forward events

void SetQtWidget(QWidget* widget) {
    this->qtWidget = widget;
}

// Override the OnLeftButtonDown event to forward it to the Qt widget
void OnLeftButtonDown() override {
    if (this->qtWidget) {
        // Get the click position in VTK coordinates
        int* clickPos = this->GetInteractor()->GetEventPosition();
        QPoint globalPos(clickPos[0], clickPos[1]);

        // Convert VTK coordinates to Qt widget coordinates
        QPoint widgetPos = qtWidget->mapFromGlobal(globalPos);

        // Create a QMouseEvent for left-button click with translated coordinates
        QMouseEvent event(QEvent::MouseButtonPress, widgetPos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
        QApplication::sendEvent(this->qtWidget, &event);  // Forward event to Qt widget
    }
    // Continue with the default behavior
    vtkInteractorStyleTrackballCamera::OnLeftButtonDown();
}

void OnLeftButtonUp() override {
    if (this->qtWidget) {
        int* clickPos = this->GetInteractor()->GetEventPosition();
        QPoint globalPos(clickPos[0], clickPos[1]);
        QPoint widgetPos = qtWidget->mapFromGlobal(globalPos);

        QMouseEvent event(QEvent::MouseButtonRelease, widgetPos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
        QApplication::sendEvent(this->qtWidget, &event);
    }
    vtkInteractorStyleTrackballCamera::OnLeftButtonUp();
}

void OnMouseMove() override {
    if (this->qtWidget) {
        int* movePos = this->GetInteractor()->GetEventPosition();
        QPoint globalPos(movePos[0], movePos[1]);
        QPoint widgetPos = qtWidget->mapFromGlobal(globalPos);

        QMouseEvent event(QEvent::MouseMove, widgetPos, Qt::NoButton, Qt::NoButton, Qt::NoModifier);
        QApplication::sendEvent(this->qtWidget, &event);
    }
    vtkInteractorStyleTrackballCamera::OnMouseMove();
}

};

int main(int argc, char* argv)
{
// Initialize Qt application
QApplication app(argc, argv);

// Create the VTK renderer and render window
vtkNew<vtkRenderer> renderer;
vtkNew<vtkGenericOpenGLRenderWindow> renderWindow;
renderWindow->AddRenderer(renderer);

// Create a QVTK widget for embedding VTK in Qt
QVTKOpenGLNativeWidget* vtkWidget = new QVTKOpenGLNativeWidget;
vtkWidget->setRenderWindow(renderWindow);

// Create a basic QWidget with a QPushButton
QWidget* qtWidget = new QWidget();
QVBoxLayout* layout = new QVBoxLayout(qtWidget);
QPushButton* button = new QPushButton("Click Me");
layout->addWidget(button);
qtWidget->setLayout(layout);

// Set up the vtkQWidgetWidget to embed the Qt widget inside the VTK render window
vtkNew<vtkQWidgetWidget> vtkWidgetWidget;
vtkWidgetWidget->CreateDefaultRepresentation();
vtkWidgetWidget->SetWidget(qtWidget);
// Get the interactor from the render window
vtkRenderWindowInteractor* interactor = vtkWidget->renderWindow()->GetInteractor();

// Create a custom interactor style to handle events
CustomInteractorStyle* customStyle = CustomInteractorStyle::New();  // Use the manual New() implementation
customStyle->SetQtWidget(qtWidget);  // Set the Qt widget to forward events
interactor->SetInteractorStyle(customStyle);

// Enable the vtkWidgetWidget interaction
vtkWidgetWidget->SetInteractor(interactor);
vtkWidgetWidget->SetCurrentRenderer(renderer);
vtkWidgetWidget->On();

// Handle QPushButton click event
QObject::connect(button, &QPushButton::clicked, []() {
	std::cout << "Button clicked" << std::endl;
});

// Set up the main window layout
QWidget* mainWindow = new QWidget;
QVBoxLayout* mainLayout = new QVBoxLayout(mainWindow);
mainLayout->addWidget(vtkWidget);
mainWindow->setLayout(mainLayout);
mainWindow->resize(800, 600);
mainWindow->show();

// Start the Qt event loop
return app.exec();

}

Hello,

It is not advised to implement the constructor by hand for classes derived from VTK classes. Instead, use a VTK macro to correct use a VTK object factory:

// Implementation of the New() function for this class.
vtkStandardNewMacro(CustomInteractorStyle);

Place this as a free standing line of code in a .cpp file (not inside class declaration nor definition).

If you still want to declare and define the class in a single shot, please, find how to correctly implement the New() function here: Header-only vtk-derived class .

best,

PC

Thanks for the suggestions. But, Does it make a difference in receiving the event and passing it to Qt ?

Likely. You have to use the VTK factories to make derived class right.

Hi Paulo,
I have changed the code as per your suggestions but it is not helping.

Hello,

Please, take a look at this one:

This one works.

best,

PC