Search code examples
pythonpyqt5vtk

vtkBoxWidget not working with PyQt5 application


I am trying to embed vtk rendering code in PyQt5 with with QVTKRenderWindowInteractor. When I tried to use vtkBoxWidget inside it, program crashed. Without vtkBoxWidget (enclosed within two lines in below code ), its working fine. Can you please help me find the issue? I am trying to manually crop the rendered object using a bounding box with the help of vtkBoxWidget.

CODE:

from PyQt5.QtWidgets import QApplication, QWidget, QMainWindow, QFrame, QVBoxLayout
import sys
import vtk
from PyQt5 import QtGui
from vtk.qt.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor

class MainWindow(QMainWindow):

    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)
        self.frame = QFrame()
        self.vl = 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()
        self.iren.SetInteractorStyle(vtk.vtkInteractorStyleTrackballCamera())

        # 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)

        ###################################################################################
        boxWidget = vtk.vtkBoxWidget()
        boxWidget.SetInteractor(self.iren)
        boxWidget.SetPlaceFactor(1.0)
        boxWidget.SetRotationEnabled(0)
        planes = vtk.vtkPlanes()

        def ClipVolumeRender(obj, event):
            obj.GetPlanes(planes)
            mapper.SetClippingPlanes(planes)

        boxWidget.SetProp3D(actor)
        boxWidget.PlaceWidget()
        boxWidget.InsideOutOn()
        boxWidget.AddObserver("InteractionEvent", ClipVolumeRender)
        boxWidget.On()
        ###################################################################################

        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 = QApplication(sys.argv)
    window = MainWindow()
    sys.exit(app.exec_())

Solution

  • The problem is that boxWidget is a local variable that is eliminated by python, so afterwards the application tries to access that object but it no longer has allocated memory generating Segmentation fault. The solution is to extend the scope by changing boxWidget with self.boxWidget.