0
votes

I am new here. Here are my specs: Mac OS X, python 3.7.4, VTK 8.1.2, and PyQt 5.13.1

I am trying to build, in python, and application using PyQT5 where I can run the following example:

https://vtk.org/Wiki/VTK/Examples/Python/Interaction/HighlightAPickedActor

where there is a bunch of spheres in a 3D space where one could pick one sphere turning red.

Here is my code:

import sys
import vtk

try:
    from PyQt5.QtWidgets import QMainWindow, QAction, qApp, QApplication
    from PyQt5.QtWidgets import QWidget, QSizePolicy, QPushButton, QVBoxLayout, QFrame

    from PyQt5.QtGui import QIcon
    from PyQt5.QtCore import Qt, pyqtSignal, QTimer, QObject, QSize, QEvent
except ImportError:
    raise ImportError("Cannot load either PyQt5")

from vtk.qt.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor    


NUMBER_OF_SPHERES = 10

class MouseInteractorHighLightActor(vtk.vtkInteractorStyleTrackballCamera):

    def __init__(self,parent=None):
        self.AddObserver("LeftButtonPressEvent",self.leftButtonPressEvent)

        self.LastPickedActor = None
        self.LastPickedProperty = vtk.vtkProperty()

    def leftButtonPressEvent(self,obj,event):
        clickPos = self.GetInteractor().GetEventPosition()

        picker = vtk.vtkPropPicker()
        picker.Pick(clickPos[0], clickPos[1], 0, self.GetDefaultRenderer())

        # get the new
        self.NewPickedActor = picker.GetActor()

        # If something was selected
        if self.NewPickedActor:
            # If we picked something before, reset its property
            if self.LastPickedActor:
                self.LastPickedActor.GetProperty().DeepCopy(self.LastPickedProperty)


            # Save the property of the picked actor so that we can
            # restore it next time
            self.LastPickedProperty.DeepCopy(self.NewPickedActor.GetProperty())
            # Highlight the picked actor by changing its properties
            self.NewPickedActor.GetProperty().SetColor(1.0, 0.0, 0.0)
            self.NewPickedActor.GetProperty().SetDiffuse(1.0)
            self.NewPickedActor.GetProperty().SetSpecular(0.0)

            # save the last picked actor
            self.LastPickedActor = self.NewPickedActor

        self.OnLeftButtonDown()
        return

class Menu(QMainWindow):

    def __init__(self):
        super().__init__()
        self.initUI()


    def initUI(self):               

        exitAct = QAction(QIcon('exit.png'), ' &Quit', self)   
        exitAct.setShortcut('Ctrl+Q')
        exitAct.setStatusTip('Exit application')
        exitAct.triggered.connect(qApp.quit)

        self.statusBar()

        menubar = self.menuBar()
        menubar.setNativeMenuBar(False)
        fileMenu = menubar.addMenu('&File')
        fileMenu.addAction(exitAct)

        bar = self.menuBar()
        file = bar.addMenu("Edit")
        file.addAction("New")

        self.setGeometry(300, 300, 300, 200)
        self.setWindowTitle('Simple menu')    
        self.show()

        self.frame = QFrame()
        self.vl = QVBoxLayout()
        self.vtkWidget = QVTKRenderWindowInteractor(self.frame)

        self.vl.addWidget(self.vtkWidget)



        self.renderer = vtk.vtkRenderer()
        self.renderer.SetBackground(.3, .4, .5 )

        self.renwin = vtk.vtkRenderWindow()
        self.renwin.AddRenderer(self.renderer)



        # An interactor
        self.inter = vtk.vtkRenderWindowInteractor()
        self.inter.SetRenderWindow(self.renwin)

        # add the custom style
        self.style = MouseInteractorHighLightActor()
        self.style.SetDefaultRenderer(self.renderer)
        self.vtkWidget.GetRenderWindow().AddRenderer(self.renderer)
        #self.iren = self.vtkWidget.GetRenderWindow().GetInteractor()
        self.inter.SetInteractorStyle(self.style)
        #self.iren.SetInteractorStyle(self.inter)
        #self.iren = self.vtkWidget.GetRenderWindow().SetInteractor(self.inter)


        # Add spheres to play with
        for i in range(NUMBER_OF_SPHERES):
            source = vtk.vtkSphereSource()

            # random position and radius
            x = vtk.vtkMath.Random(-5,5)
            y = vtk.vtkMath.Random(-5,5)
            z = vtk.vtkMath.Random(-5,5)
            radius = vtk.vtkMath.Random(.5, 1.0)

            source.SetRadius(radius)
            source.SetCenter(x, y, z)
            source.SetPhiResolution(11)
            source.SetThetaResolution(21)

            mapper = vtk.vtkPolyDataMapper()
            mapper.SetInputConnection(source.GetOutputPort())
            actor = vtk.vtkActor()
            actor.SetMapper(mapper)

            r = vtk.vtkMath.Random(.4, 1.0)
            g = vtk.vtkMath.Random(.4, 1.0)
            b = vtk.vtkMath.Random(.4, 1.0)
            actor.GetProperty().SetDiffuseColor(r, g, b)
            actor.GetProperty().SetDiffuse(.8)
            actor.GetProperty().SetSpecular(.5)
            actor.GetProperty().SetSpecularColor(1.0,1.0,1.0)
            actor.GetProperty().SetSpecularPower(30.0)

            #renderer.AddActor(actor)
            self.renderer.AddActor(actor)


        self.renderer.ResetCamera()

        self.frame.setLayout(self.vl)
        self.setCentralWidget(self.frame)

        self.show()

        self.inter.Initialize()
        self.inter.Start()

if __name__ == '__main__':

    app = QApplication(sys.argv)
    ex = Menu()
    sys.exit(app.exec_())        

However, though I get my code running, I get two separate windows: the "menu" on one side and the vtk renderer as a different window. I would like to know what I am doing wrong, if you are eager to help me.

Thank you in advance

1

1 Answers

1
votes

The second window pops up because in Menu.initUI you are creating separate instances of vtkRenderWindow and vtkRenderWindowInteractor instead of using the ones provided by your QVTKRenderWindowInteractor object. So you should replace this line

self.renwin = vtk.vtkRenderWindow()

with this

self.renwin = self.vtkWidget.GetRenderWindow()

and these two lines

self.inter = vtk.vtkRenderWindowInteractor()
self.inter.SetRenderWindow(self.renwin)

with this one

self.inter = self.renwin.GetInteractor()