Python&;VTK&;PyQt5:如何在def _uinit_;中渲染vtk屏幕截图?

Python&;VTK&;PyQt5:如何在def _uinit_;中渲染vtk屏幕截图?,python,pyqt,pyqt5,vtk,qvtkwidget,Python,Pyqt,Pyqt5,Vtk,Qvtkwidget,我做了什么: 使用PyQt5和VTK创建一个应用程序,我在2QTK小部件中添加了2VTK渲染 在每个VTK渲染中,我读取一个.stl文件并显示它 我添加了一个功能屏幕截图,它可以屏幕截图VTK渲染和保存这张图片 我添加一个菜单栏,我可以单击菜单栏和屏幕快照VTK渲染 我想做的是: 我想在加载VTK渲染后执行screen_shot,我在def_uuuinit_uuu中写入它。但这样我只能得到一张100*30的照片(事实上是900*900)。当我点击菜单,我会得到一张900*900的图片 也许我的描

我做了什么:

  • 使用PyQt5和VTK创建一个应用程序,我在2QTK小部件中添加了2VTK渲染

  • 在每个VTK渲染中,我读取一个.stl文件并显示它

  • 我添加了一个功能屏幕截图,它可以屏幕截图VTK渲染和保存这张图片

  • 我添加一个菜单栏,我可以单击菜单栏和屏幕快照VTK渲染

  • 我想做的是:

    我想在加载VTK渲染后执行screen_shot,我在def_uuuinit_uuu中写入它。但这样我只能得到一张100*30的照片(事实上是900*900)。当我点击菜单,我会得到一张900*900的图片

    也许我的描述无法理解,这是我的代码:

    class MainWindow(QtWidgets.QMainWindow):
        def __init__(self, parent=None):
            QtWidgets.QMainWindow.__init__(self, parent)
    
            self.workspace = ""
            self.data_path = ""
            self.data_index = 0
            self.bkcolor = (1.0, 1.0, 1.0)
    
            self.frame = QtWidgets.QFrame()
            self.setWindowTitle("PythonVTKViewer")
            # self.frame.setLayout(self.box)
    
            self.stl_interactor = QtWidgets.QHBoxLayout()
            self.init_menubar()
            self.showMaximized()
            self.load_Interactor()
            self.shot_screen()
    
        def init_menubar(self):
            # init a menubar
            menubar = self.menuBar()
    
            fileMenu = menubar.addMenu('&Function')
    
            self.screen_shot_button = QtWidgets.QAction('ScreenShot', self)
            self.screen_shot_button.setShortcut('Ctrl+S')
            self.screen_shot_button.setStatusTip('ScreenShot')
            self.screen_shot_button.triggered.connect(self.shot_screen)
            fileMenu.addAction(self.screen_shot_button)
    
        def load_Interactor(self):
            # Create two render windows
            self.vtkWidget_left = QVTKRenderWindowInteractor(self.frame)
            self.vtkWidget_right = QVTKRenderWindowInteractor(self.frame)
    
            self.stl_interactor.addWidget(self.vtkWidget_left)
            self.stl_interactor.addWidget(self.vtkWidget_right)
    
            # Left renderer and right renderer
            self.ren_left = vtk.vtkRenderer()
            self.vtkWidget_left.GetRenderWindow().AddRenderer(self.ren_left)
            self.renWinLeft = self.vtkWidget_left.GetRenderWindow()
            self.iren_left = self.renWinLeft.GetInteractor()
    
            self.ren_right = vtk.vtkRenderer()
            self.vtkWidget_right.GetRenderWindow().AddRenderer(self.ren_right)
            self.iren_right = self.vtkWidget_right.GetRenderWindow().GetInteractor()
    
            # read stl file
            upper_path = os.path.join(self.workspace, "stl/scanner/start/UpperTeeth.stl")
            lower_path = os.path.join(self.workspace, "stl/scanner/start/LowerTeeth.stl")
            self.init_stl("./temp/upperteeth.stl")
            self.init_stl("./temp/lowerteeth.stl")
    
            self.frame.setLayout(self.stl_interactor)
    
            self.setCentralWidget(self.frame)
    
            self.ren_left.SetBackground(self.bkcolor[0], self.bkcolor[1], self.bkcolor[2])
            self.ren_right.SetBackground(self.bkcolor[0], self.bkcolor[1], self.bkcolor[2])
    
            # adjust camera
            self.init_camera()
    
            self.iren_left.Initialize()
            self.iren_right.Initialize()
    
        def init_stl(self, file):
            # reader = Reader.read_data(file)
            reader = vtk.vtkSTLReader()
            if "upper" in file or "Upper" in file:
                reader.SetFileName(file)
                reader.Update()
    
                self.mapper_left = vtk.vtkPolyDataMapper()
                self.mapper_left.SetInputConnection(reader.GetOutputPort())
                self.actor_left = vtk.vtkActor()
                self.actor_left.SetMapper(self.mapper_left)
                self.ren_left.AddActor(self.actor_left)
            else:
                reader.SetFileName(file)
                reader.Update()
    
                self.mapper_right = vtk.vtkPolyDataMapper()
                self.mapper_right.SetInputConnection(reader.GetOutputPort())
                self.actor_right = vtk.vtkActor()
                self.actor_right.SetMapper(self.mapper_right)
                self.ren_right.AddActor(self.actor_right)
    
        def init_camera(self):
            self.ren_left.GetActiveCamera().SetFocalPoint(0, 0, 0)
            self.ren_left.GetActiveCamera().SetPosition(0, 0, -150)
            self.ren_left.GetActiveCamera().Roll(90)
            self.ren_left.GetActiveCamera().ParallelProjectionOn()
            self.ren_left.GetActiveCamera().SetParallelScale(40)
    
            self.ren_right.GetActiveCamera().SetFocalPoint(0, 0, 0)
            self.ren_right.GetActiveCamera().SetPosition(0, 0, 150)
            self.ren_right.GetActiveCamera().Roll(270)
            self.ren_right.GetActiveCamera().ParallelProjectionOn()
            self.ren_right.GetActiveCamera().SetParallelScale(40)
    
        def shot_screen(self):
            if os.path.exists("./temp/input/upper.png"): os.remove("./temp/input/upper.png")
            elif os.path.exists("./temp/input/lower.png"): os.remove("./temp/input/lower.png")
    
            filter = vtk.vtkRenderLargeImage()
            filter.SetMagnification(1)
            filter.SetInput(self.ren_left)
            writer = vtk.vtkPNGWriter()
            writer.SetFileName("./temp/input/upper.png")
            writer.SetInputConnection(filter.GetOutputPort())
            writer.Write()
    
            filter = vtk.vtkRenderLargeImage()
            filter.SetMagnification(1)
            filter.SetInput(self.ren_right)
            writer = vtk.vtkPNGWriter()
            writer.SetFileName("./temp/input/lower.png")
            writer.SetInputConnection(filter.GetOutputPort())
            writer.Write()
    
    
    
    
    if __name__ == "__main__":
        app = QtWidgets.QApplication(sys.argv)
        window = MainWindow()
        sys.exit(app.exec_())
    

    如何在def_uuuinit_uuuu中进行屏幕截图?我需要完成此功能吗?

    您需要等待主事件循环启动并且GUI完全呈现后,才能进行屏幕截图。这意味着启动主事件循环的
    app.exec()
    ,应该在
    MainWindow.shot\u屏幕之前执行。在
    main window中实现这一点的一种方法是使用单个快照
    QTimer
    来延迟
    main window.shot\u screen
    的执行,直到事件循环开始之后,例如

    class MainWindow(QtWidgets.QMainWindow):
        def __init__(self, parent=None):
            ...
            QtCore.QTimer.singleShot(10, self.shot_screen)
    
        ...
    

    \uuuu init\uuu
    方法的末尾,输入:

    QtWidgets.QApplication.instance().processEvents()
    self.shot_screen()
    
    qtwidts.QApplication.instance()
    获取您的
    app
    .processEvents()
    会执行一次事件循环,允许@Heike在回答中提到的必要初始化发生
    app.exec()
    大致相当于:

    while windows_are_open:
        app.processEvents()