VTK和PyQt5:如何使用滑块更改半径值后刷新显示

时间:2018-12-14 07:48:44

标签: python pyqt pyqt5 vtk qvtkwidget

我正在尝试使用VTK和PyQt5编写python代码,以显示用户可以使用滑块自定义的VTK Sphere。窗口和小部件的概念还可以,问题是当我使用滑块更改球体半径的值时,渲染窗口需要单击以更新视图。我希望滑块移动后场景会自动更新。我尝试了.reinitialize(),.Update(),.CameraReset()之类的方法,但要么不存在,要么就无法正常工作

这是代码:

    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(source.SetRadius)
   source.Update()
   source.Modified()




   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())
   mapper.Update()

  # 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()
   iren.Render()

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




if __name__ == '__main__':
   window()

提前谢谢!

2 个答案:

答案 0 :(得分:1)

尝试:
1)修改:

...
from PyQt5 import Qt

def chgdValue(iren):
    iren.GetRenderWindow().Render()

def window():
...

2)修改:

...
Slider_1.valueChanged.connect(source.SetRadius)
Slider_1.valueChanged.connect(lambda x: chgdValue(iren))
source.Update()
...

.CameraReset()也可以工作,但是它可以缩放场景,您必须添加一些要比较的东西。

答案 1 :(得分:0)

每当我要在程序化(非交互式)更改后强制对其进行更新时,我都会在渲染窗口交互器上使用reintialize。在您的情况下,由于滑块是应用程序其余部分的一部分,而不是渲染窗口交互器自身内部的交互,因此您需要调用reinitialize来强制对其进行更新。

调用iren.ReInitialize()(注意大小写)。 VTKRenderWindowInteractor的文档在这里:

https://www.vtk.org/doc/release/7.1/html/classvtkRenderWindowInteractor.html

此答案也显示为与问题相关的评论的一部分:

pyqt and VTK : problem to connect slider to vtk object