QPainter::begin: Paint device returned engine == 0, type: 1
If any of you will be at SciPy2022 this week, this might be a great problem to debug in a Sprint Session (July 16-17) to collaborate with other package maintainers.
On Windows 10 with PySide6, using QVTKRenderWindowInteractor
produces the following error
QPainter::begin: Paint device returned engine == 0, type: 1
every time the screen is updated.
From the PySide6 QPaintEngine docs, the error is saying Qt
thinks I am on X11
:
QPaintEngine.X11 == 0
QPainEngine.Windows == 1
After debugging in VSCode with the following launch.json
so the debugger goes into packages:
{
"configurations": [
{
"name": "Python: Current File",
"type": "python",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal",
"justMyCode": false
}
],
}
I found the error happens when rwi.py::QVTKRenderWindowInteractor.paintEngine()
is called in response to a Paint
event:
def paintEngine(self):
return None
I also noticed pyvistaqt.rwi::QVTKRenderWindowInteractor.__init__()
sets widget attribute
self.setAttribute(WidgetAttribute.WA_PaintOnScreen)
From the PyQt5, PySide2, PyQt6, and PySide6 docs, this flag is only supported on X11
and requires returning NULL (None
) from paintEngine
:
Hence, an alternative is needed for non-X11
systems (Windows
, Mac
).
This issue first appeared for mayavi
2 years ago in Problem when using QGLWidget #969 (as yet unresolved) and has resurfaced in pyvistaqt
in QPainter::begin: Paint device returned engine == 0, type: 1 #196.
Update:
When using QVTKRWIBaseClass = QWidget
, if self.setAttribute(Qt.WA_PaintOnScreen)
is commented out (and paintEngine
still returning None
), I see rendering issues both in the @dgobbi QtConeExample.py and with pyvistaqt
(MRE below).
Hence, contrary to the PySide6 docs, it does seem self.setAttribute(WidgetAttribute.WA_PaintOnScreen)
sets single-buffering on Windows.
OS: Windows 10 x64-bit
Python: 3.8.10
VTK: 9.1.0
(using vtkmodules
)
Qt Binding: PySide6
QtConeExample.py Error
PyVistaQt Error
MRE
from pyvistaqt import QtInteractor, MainWindow
from qtpy import QtWidgets
class Window(MainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle('Example')
self.layout_ = QtWidgets.QVBoxLayout()
self.container = QtWidgets.QFrame()
self.container.setLayout(self.layout_)
self.setCentralWidget(self.container)
self.plotter = QtInteractor(parent=self.container)
self.plotter.add_axes()
self.layout_.addWidget(self.plotter)
self.plotter.show()
self.signal_close.connect(self.plotter.close)
if __name__ == '__main__':
app = QtWidgets.QApplication([])
window = Window()
window.show()
app.exec_()