Minimum working example:
from sys import exit
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QHBoxLayout, QLabel, QFrame
from vtk.qt.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor
import vtkmodules.all as vtk
from vtkmodules.util import numpy_support
import numpy as np
vtk_out = vtk.vtkOutputWindow()
vtk_out.SetDisplayMode(0)
def generate_qtvtk_sphere(parent):
frame = QFrame(parent)
vtkWidget = QVTKRenderWindowInteractor(frame)
ren = vtk.vtkRenderer()
vtkWidget.GetRenderWindow().AddRenderer(ren)
iren = vtkWidget.GetRenderWindow().GetInteractor()
# Create source
source = vtk.vtkSphereSource()
source.SetCenter(0, 0, 0)
source.SetRadius(5.0)
# Create a mapper
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputConnection(source.GetOutputPort())
# Create an actor
actor = vtk.vtkActor()
actor.SetMapper(mapper)
ren.AddActor(actor)
ren.ResetCamera()
iren.Initialize()
iren.Start()
return vtkWidget
def generate_qtvtk_imagedata(parent):
frame = QFrame(parent)
vtkWidget = QVTKRenderWindowInteractor(frame)
random_array = np.random.random([10, 600, 800])
vtk_image_data = vtk.vtkImageData()
image_array = numpy_support.numpy_to_vtk(random_array.ravel(), deep=True, array_type=vtk.VTK_TYPE_UINT16)
vtk_image_data.GetPointData().SetScalars(image_array)
vtk_image_data.Modified()
reslice = vtk.vtkImageReslice()
reslice.SetInputData(vtk_image_data)
reslice.SetOutputDimensionality(2)
ren = vtk.vtkRenderer()
vtkWidget.GetRenderWindow().AddRenderer(ren)
iren = vtkWidget.GetRenderWindow().GetInteractor()
# Create an actor
actor = vtk.vtkImageActor()
actor.GetMapper().SetInputConnection(reslice.GetOutputPort())
ren.SetBackground(50, 50, 50)
ren.AddActor(actor)
ren.ResetCamera()
interactorStyle = vtk.vtkInteractorStyleImage()
vtkWidget.SetInteractorStyle(interactorStyle)
vtkWidget.GetRenderWindow().SetInteractor(vtkWidget)
vtkWidget.GetRenderWindow().Render()
iren.Initialize()
iren.Start()
return vtkWidget
app = QApplication([])
main_window = QMainWindow()
main_widget = QWidget()
main_layout = QHBoxLayout()
main_widget.setLayout(main_layout)
qtvtk_widget_sphere = generate_qtvtk_sphere(main_widget)
qtvtk_widget_image = generate_qtvtk_imagedata(main_widget)
main_layout.addWidget(qtvtk_widget_image)
main_layout.addWidget(qtvtk_widget_sphere)
main_window.setCentralWidget(main_widget)
main_window.show()
app.exec()
The output of this code should be a pyqt window with a sphere on one side and a randomly-generated black square on the other. The square is representative of the datasets that I normally deal with.
The relevant packages in my conda env are:
The full error I get looks like this:
Original post follows:
In my application, I have two QVTKRenderWindowInteractor
, on two different QWidgets, that are mostly independent from each other - there's a function outside the interactors that updates the contents of both interactors at the same thing, but that's it.
Whenever the application displays both interactors, I get the following error when the app closes:
2022-08-23 13:51:07.522 ( 10.079s) [ ]vtkWin32OpenGLRenderWin:267 ERR| vtkWin32OpenGLRenderWindow (00000194B174E4C0): wglMakeCurrent failed in MakeCurrent(), error: ࣐Ɣ
The error part in the end looks like this on the debugger
and there's usually a lot of these errors that pop up.
My other application (same idea, qt, same interactor, same set-up) has these lines in the beginning of the code
vtk_out = vtkOutputWindow()
vtk_out.SetDisplayMode(0)
which suppresses the errors for that one.
But in my other progra,, I need to use a QWorker/QThread in order to update the interactor, and outputting the error to console doesn't work anymore (it creates a new window with the same error, and then freezes everything).
I just want to know what the heck these errors are and how to get rid of them.
Also, the code I'm using the setup the interactor is as follows:
In the widget:
self._frame = QGroupBox()
self.interactor = ViewerPanelVTK(self._frame)
layout = QVBoxLayout(self)
layout.addWidget(self.interactor)
where
class ViewerPanelVTK(QVTKRenderWindowInteractor):
def __init__(self, parent=None):
super().__init__(parent)
self.panel_actor = vtkImageActor()
self.panel_renderer = vtkRenderer()
self.window = self.GetRenderWindow()
Found the answer myself eventually in the VTK discourse forum.
Apparently the widget needs to be closed so that this error won't show.
The sample code from the original answer follows:
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import sys
from vtk.qt.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor
import vtk
class vtkWin(QWidget):
def __init__(self):
super().__init__()
layout = QVBoxLayout()
self.setLayout(layout)
self.vtkWidget = QVTKRenderWindowInteractor()
layout.addWidget(self.vtkWidget)
render = vtk.vtkRenderer()
self.vtkWidget.GetRenderWindow().AddRenderer(render)
cone_a=vtk.vtkConeSource()
coneMapper = vtk.vtkPolyDataMapper()
coneMapper.SetInputConnection(cone_a.GetOutputPort())
coneActor = vtk.vtkActor()
coneActor.SetMapper(coneMapper)
render.AddActor(coneActor)
self.vtkWidget.GetRenderWindow().Render()
def closeEvent(self, QCloseEvent):
super().closeEvent(QCloseEvent)
self.vtkWidget.Finalize() ############################ important
class MainWindow(QWidget):
def __init__(self):
super().__init__()
layout = QHBoxLayout()
self.setLayout(layout)
self.w1 = vtkWin()
self.w2 = vtkWin()
layout.addWidget(self.w1)
layout.addWidget(self.w2)
def closeEvent(self, QCloseEvent):
super().closeEvent(QCloseEvent)
self.w1.close()
self.w2.close()
if __name__ == '__main__':
app = QApplication(sys.argv)
w = MainWindow()
w.show()
app.exec_()