在PyQT5窗口中嵌入VTK对象

5
我正在为3D模型开发一个生成设计项目。我需要创建一个简单的QT应用程序,允许用户使用VTK查看网格,并包括一些按钮来反馈到生成算法中。
GUI对我来说是全新的,所以我很难将这里的代码集成到更广泛的程序中。目前我仅尝试在查看器中创建一个单独的按钮和一个3D圆锥体。
我的代码在运行时崩溃了。它使用了给定链接中的QVTKRenderWindowInteractor()对象,并将该对象直接粘贴到文件中。
try:
    import sys
    import vtk
    from PyQt5.QtWidgets import QWidget, QSizePolicy, QApplication, QPushButton, QVBoxLayout
    from PyQt5.QtCore import Qt, pyqtSignal, QTimer, QObject, QSize, QEvent
except ImportError:
    raise ImportError("无法加载PyQt5")
import vtk
class neuralDesignerApp(QWidget): def __init__(self): super(QWidget,self).__init__() self.initUI()
def initUI(self):
app = QApplication(['QVTKRenderWindowInteractor']) vtkWindow = QVTKRenderWindowInteractor(self) vtkWindow.Initialize() vtkWindow.Start() ren = vtk.vtkRenderer() vtkWindow.GetRenderWindow().AddRenderer(ren)
cone = vtk.vtkConeSource() cone.SetResolution(8)
coneMapper = vtk.vtkPolyDataMapper() coneMapper.SetInputConnection(cone.GetOutputPort())
coneActor = vtk.vtkActor() coneActor.SetMapper(coneMapper) ren.AddActor(coneActor)
btn1 = QPushButton("Button 1", self)
vbox = QVBoxLayout() vbox.addWidget(vtkWindow) vbox.addWidget(btn1)
self.setLayout(vbox)
self.setGeometry(300, 300, 250, 150) self.setWindowTitle('Neural Designer') self.show()
1个回答

9
当您调用方法Start()时,您正在启动事件循环,这意味着以下指令将不会执行。通常情况下,在定义角色、映射器等之后,即在完成VTK管道之后,您会启动事件循环。
您查看过这个示例吗?https://www.vtk.org/Wiki/VTK/Examples/Python/Widgets/EmbedPyQt它可以正常工作,但假设您已经安装了PyQt4。为了与PyQt5配合使用,我进行了一些更改。请尝试这个:
import sys
import vtk
from PyQt5 import QtCore, QtGui
from PyQt5 import Qt

from vtk.qt.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor

class MainWindow(Qt.QMainWindow):

    def __init__(self, parent = None):
        Qt.QMainWindow.__init__(self, parent)

        self.frame = Qt.QFrame()
        self.vl = Qt.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()

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

        self.ren.AddActor(actor)

        self.ren.ResetCamera()

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

        self.show()
        self.iren.Initialize()
        self.iren.Start()


if __name__ == "__main__":
    app = Qt.QApplication(sys.argv)
    window = MainWindow()
    sys.exit(app.exec_())

重要提示:如果您的Qt应用程序变得越来越复杂,并且将在其中使用多个 QVTKRenderWindowInteractor 对象,则不要通过 Start()方法调用交互器。否则,如我之前所提到的,您会在Qt应用程序内创建另一个不必要的事件循环( app.exec()启动Qt循环)。在这种情况下,我认为您应该在声明所需对象后调用 app.exec()。更多信息可以在以下链接中找到:

非常非常非常感谢,你不仅仅是救了我的一天,你还救了我数周。最好的祝福。 - smoothumut
顺便提一下,应该使用"from vtkmodules.qt.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor"而不是"from vtk.qt.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor"。 - smoothumut

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接