首页 文章

在PyQT5窗口中嵌入VTK对象

提问于
浏览
1

我正在研究3D模型的生成设计项目 . 我需要创建一个简单的QT应用程序,允许用户使用VTK查看网格,并包含一些按钮,用于反馈生成算法 .

GUI对我来说是一个全新的东西,所以我非常难以理解如何将here的代码集成到一个更广泛的程序中 . 现在我只是想在 Spectator 中创建一个按钮和一个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("Cannot load either 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 回答

  • 5

    当您调用方法 Start() 时,您正在启动事件循环,这意味着将不会执行以下指令 . 简单地说,在完成VTK管道之后,即在定义了actor,mappers等之后启动事件循环 .

    你在这里检查了这个例子吗? 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() . 可在以下链接中找到更多信息:

相关问题