pyqt and VTK : problem to connect slider to vtk object [duplicate]

时光总嘲笑我的痴心妄想 提交于 2019-12-23 04:52:26

问题


I'm dealing with some issues, using vtk in PyQt5. The problem is that I have a vtk sphere with an initial radius value and some sliders to connect to the sphere dans QLCD Numbers. Indeed, what I want is to have one of the sliders set at 128 at first dans when the user slide to change the value, this value will be displayed in the QLCDNumber and the current value of the slider will be taken to change the Radius of the VTK Sphere.

Here's my code :

    import sys
from PyQt5.QtWidgets import QApplication, QWidget, QSlider, QLCDNumber
from PyQt5.QtWidgets import (QApplication, QCheckBox, QGridLayout, QGroupBox,
                             QMenu, QPushButton, QRadioButton, QVBoxLayout, QWidget, QSlider,QLineEdit,QLabel)
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5 import *
import vtk
from vtk.qt.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor
from PyQt5 import Qt

def window():

   source = vtk.vtkSphereSource()
   source.SetCenter(0, 0, 0)
   source.SetRadius(5.0)

   app = QApplication(sys.argv)
   win = QWidget()

   Display_1 = QLCDNumber(3)
   Display_2 = QLCDNumber(3)
   Display_3 = QLCDNumber(3)

   Display_1.setSegmentStyle(QLCDNumber.Flat)
   Display_2.setSegmentStyle(QLCDNumber.Flat)
   Display_3.setSegmentStyle(QLCDNumber.Flat)

   Display_1.display(128)
   Display_2.display(128)
   Display_3.display(128)

   Slider_1 = QSlider(QtCore.Qt.Horizontal)
   Slider_1.setMinimum(0)
   Slider_1.setMaximum(255)
   Slider_1.setValue(128)
   Slider_1.valueChanged.connect(Display_1.display)
   Slider_1.valueChanged.connect(changevalue(Slider_1,source))

   Slider_2 = QSlider(QtCore.Qt.Horizontal)
   Slider_2.setMinimum(0)
   Slider_2.setMaximum(255)
   Slider_2.setValue(128)
   Slider_2.valueChanged.connect(Display_2.display)


   Slider_3 = QSlider(QtCore.Qt.Horizontal)
   Slider_3.setMinimum(0)
   Slider_3.setMaximum(255)
   Slider_3.setValue(128)
   Slider_3.valueChanged.connect(Display_3.display)

   label_1 = QLabel("Label_1")
   label_1.setAlignment(QtCore.Qt.AlignCenter)

   label_2 = QLabel("Label_2")
   label_2.setAlignment(QtCore.Qt.AlignCenter)

   label_3 = QLabel("Label_3")
   label_3.setAlignment(QtCore.Qt.AlignCenter)  

   vbox = QtWidgets.QVBoxLayout()


   vbox.addWidget(label_1)
   vbox.addWidget(Display_1)
   vbox.addWidget(Slider_1)

   vbox.addWidget(label_2)
   vbox.addWidget(Display_2)
   vbox.addWidget(Slider_2)

   vbox.addWidget(label_3)
   vbox.addWidget(Display_3)
   vbox.addWidget(Slider_3)

   vbox.addStretch()






   hbox = QtWidgets.QHBoxLayout()

   frame = QtWidgets.QFrame()
   frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
   frame.setFrameShape(QtWidgets.QFrame.StyledPanel) # Application de la forme
   frame.setFrameShadow(QtWidgets.QFrame.Raised) # application d'une ombre
   frame.setObjectName("frame") # Appellation du cadre

   #b3 = QtWidgets.QPushButton("Button3")
   #b4 = QtWidgets.QPushButton("Button4")
   hbox.addWidget(frame)
   hbox.addStretch()
   #hbox.addWidget(b4)

   vbox.addStretch()
   hbox.addLayout(vbox)
   win.setLayout(hbox)



   vtkWidget = QVTKRenderWindowInteractor(frame)
   vl = Qt.QVBoxLayout()
   vl.addWidget(vtkWidget)

   ren = vtk.vtkRenderer()
   vtkWidget.GetRenderWindow().AddRenderer(ren)
   iren = vtkWidget.GetRenderWindow().GetInteractor()



  # Create a mapper
   mapper = vtk.vtkPolyDataMapper()
   mapper.SetInputConnection(source.GetOutputPort())

  # Create an actor
   actor = vtk.vtkActor()
   actor.SetMapper(mapper)

   ren.AddActor(actor)
   ren.ResetCamera()
   frame.setLayout(vl)
   #setCentralWidget(self.frame)
   #show()
   iren.Initialize()
   iren.Start()

   win.setWindowTitle("PyQt")
   win.resize(743, 430)
   win.show()
   sys.exit(app.exec_())

def changevalue(slider,source):
   value  = slider.value()
   source.SetRadius(int(value))


if __name__ == '__main__':
   window()

When I try to use the code the python returns me the following error : "File "window.py", line 38, in window Slider_1.valueChanged.connect(changevalue(Slider_1,source)) TypeError: argument 1 has unexpected type 'NoneType'"

Any idea ?

Thanks in advance


回答1:


The connect method in PyQt is expecting a function object. Instead, you are calling a function:

changevalue(Slider_1,source)

The function changevalue doesn't return anything. In other words, it returns None.

So, when you call the line:

Slider_1.valueChanged.connect(changevalue(Slider_1,source))

what you are really doing is calling connect with None as the argument becuase this is what your function call to changevalue is returning. Instead, you need to pass it the function changevalue, but since you need to call that function with arguments, you'll need to do something like this:

...
Slider_1 = QSlider(QtCore.Qt.Horizontal)
   Slider_1.setMinimum(0)
   Slider_1.setMaximum(255)
   Slider_1.setValue(128)
   def handler():
       changevalue(Slider_1, source)
   Slider_1.valueChanged.connect(Display_1.display)
   Slider_1.valueChanged.connect(handler)
...

I ran your code with this modification and the sphere displays. However, there is one other issue and that is that when you move the sliders, your sphere doesn't update. In order to get the VTK renderer to update, you'll need to figure out how to call iren.reinitialize() in your changevalue handler, or something to this effect. The reinitialize call will cause the render window to update in response to the slider movement.



来源:https://stackoverflow.com/questions/53762876/pyqt-and-vtk-problem-to-connect-slider-to-vtk-object

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!