VTK/Examples/Python/Widgets/EmbedPyQt

From KitwarePublic
< VTK‎ | Examples‎ | Python
Jump to navigationJump to search

Minimal working example of vtk embedding in PyQt.

  • Contributed by Michka Popoff, inspired by the example from Eric E Monson
  • See notes at the end for more details.

EmbedInPyQt.py

#!/usr/bin/env python
 
import sys
import vtk
from PyQt4 import QtCore, QtGui
from vtk.qt4.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor
 
class MainWindow(QtGui.QMainWindow):
 
    def __init__(self, parent = None):
        QtGui.QMainWindow.__init__(self, parent)
 
        self.frame = QtGui.QFrame()
 
        self.vl = QtGui.QVBoxLayout()
        self.vtkWidget = QVTKRenderWindowInteractor(self.frame)
        self.vl.addWidget(self.vtkWidget)
 
        self.ren = vtk.vtkRenderer()
        self.vtkWidget.GetRenderWindow().AddRenderer(self.ren)
        self.iren = self.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)
 
        self.ren.AddActor(actor)
 
        self.ren.ResetCamera()
 
        self.frame.setLayout(self.vl)
        self.setCentralWidget(self.frame)
        
        self.show()
        self.iren.Initialize()
 
 
if __name__ == "__main__":
 
    app = QtGui.QApplication(sys.argv)
 
    window = MainWindow()
 
    sys.exit(app.exec_())

Notes

Here are some explanations about this example, in case you need more informations.

1) Why use a QFrame to embed vtk ?

QVTKRenderWindowInteractor can not be reparented. So it is not possible to put it directly in a QWidget. Some people had some trouble with this : http://public.kitware.com/pipermail/vtkusers/2009-October/054152.html

Some people did propose a fix to this by using a QtOpenGL.QGLWidget instead of a QtGui.QWidget as a parent class for the QVTKRenderWindowInteractor. You can read this ticket to see why this is not a good solution : http://vtk.org/Bug/view.php?id=13983

But as embedding is working really well with a QFrame, it's not really a problem.

2) Why not call Start() on the interactor ?

Sometimes you see examples with Start() called before Initialize(). For Qt (and PyQt), Start() will trigger the event loop, which in our case exec already does. So it's not needed. See (ref needed) this discussion to know more about this.

3) Why put show() inside the MainWindow class ?

If you do a GetRenderWindow().Render() call before the show(), this will lead to some errors, especially on Apple's OS X. In VTK 5.10.1 and 6.0.0 you would only get some odd invalid drawable errors, but since VTK 6.1 OpenGl errors are fetched and displayed.

There is a long explanation here : http://www.vtk.org/pipermail/vtk-developers/2013-July/014005.html So show() has to be called before any rendering.

See (ref needed) this discussion to know more about this.

TODO : ref needed = link to discussion "VTK OpenGL errors" on the vtk user list from the 01 nov 2013