VTK 和 PyQt5:如何在使用滑块更改半径值后刷新显示
VTK and PyQt5 : How to refresh display after changing radius value with slider
我正在尝试使用 VTK 和 PyQt5 编写一个 python 代码,它显示一个 VTK 球体,可由用户使用滑块自定义。 windows 和小部件的概念没问题,问题是当我用滑块更改球体半径的值时,渲染 windows 需要单击才能更新视图。我希望场景在滑块移动时自动更新。我尝试了一些方法,例如 .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()
提前致谢!
每当我想强制它在程序化(非交互式)更改后更新时,我都会在渲染器 window 交互器上使用重新初始化。在您的情况下,由于滑块是应用程序其余部分的一部分,而不是渲染 window 交互器本身的交互,因此您需要调用 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
试试看:
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() 也可以,但它会缩放场景,你必须添加一些东西来比较。
我正在尝试使用 VTK 和 PyQt5 编写一个 python 代码,它显示一个 VTK 球体,可由用户使用滑块自定义。 windows 和小部件的概念没问题,问题是当我用滑块更改球体半径的值时,渲染 windows 需要单击才能更新视图。我希望场景在滑块移动时自动更新。我尝试了一些方法,例如 .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()
提前致谢!
每当我想强制它在程序化(非交互式)更改后更新时,我都会在渲染器 window 交互器上使用重新初始化。在您的情况下,由于滑块是应用程序其余部分的一部分,而不是渲染 window 交互器本身的交互,因此您需要调用 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
试试看:
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() 也可以,但它会缩放场景,你必须添加一些东西来比较。