We’re upgrading a Qt/VTK application from VTK 9.0.5 → 9.5.2 (Qt 5.15.0, MSVC 2019 x86, static linking, no CMake).
Our custom interactor — a subclass of vtkGenericRenderWindowInteractor — worked flawlessly in VTK 9.0, but now in 9.5.2 it leads to:
-
black screen,
-
vtkOutputWindowwith errors like:-
"Error: No OpenGL context found", -
"GenericOpenGLRenderWindow: Window is not mapped", -
"Unable to initialize OpenGL",
-
-
crash or infinite loop if
Initialize()is called manually beforesetRenderWindow().
With the default interactor (i.e. letting QVTKOpenGLNativeWidget create it), rendering (including NIFTI) works fine.
But we need a custom interactor (e.g. to override CharEvent, add timers, sync external devices), so simply changing the style isn’t enough.
Our current approach (which worked in 9.0):
auto myInteractor = vtkSmartPointer::New(); // vtkGenericRenderWindowInteractor subclass
myInteractor->SetRenderWindow(renderWindow);
myInteractor->SetInteractorStyle(vtkSmartPointer::New());
// In 9.0: widget->setRenderWindow(renderWindow) handled the rest.
// In 9.5.2: OpenGL context never becomes valid → black screen.
widget->setRenderWindow(renderWindow); // ← expected to bind Qt adapter and initialize safely
widget->show();
renderWindow->Render();
We verified:
-
VTK_MODULE_INIT(vtkRenderingOpenGL2)andVTK_MODULE_INIT(vtkRenderingQt)are present inmain(), -
renderWindowisvtkGenericOpenGLRenderWindow, -
pipeline data (e.g.
vtkNIFTIImageReader) is valid and renders with default interactor.
Hypothesis: VTK 9.5+ became stricter about OpenGL context lifecycle and Qt interactor binding — especially around when and how Initialize() is called on a user-provided interactor.
Main question:
What is the correct, minimal, and safe way in VTK 9.5.2 to inject a custom vtkGenericRenderWindowInteractor subclass before QVTKOpenGLNativeWidget::setRenderWindow() — such that:
-
Qt event binding (
QVTKInteractorAdapter) is preserved, -
OpenGL context is correctly created and activated,
-
No manual
Initialize()is needed (or it’s done safely).
Is there a new required override (e.g. SetInteractor(), Enable()), or a timing-sensitive step we’re missing?
Thanks in advance — this seems like a subtle but critical change in interactor ownership between 9.0 and 9.5.