Insert VTK into the right spot of layout

邮差的信 提交于 2019-12-10 12:15:46

问题


I am trying to put the VTK 3D scene widget into the right spot of pyqtgraphics.GraphicsLayout(). But either the scene does not appear if i am not assigning the window as parent or if I do - the scene does not adapt to the free area, it is just floating in the upper left corner.

I am currently struggling to find a solution to put a viewbox and vtkrenderer into the same window.

One of my attempts was to assign the self.w (see below this paragraph)- which is my main window as a parent to the renderer but then I don't know how to tell the renderer to place itself in the lower right corner of the window instead of floating in the upper left corner - which also leads to overlapping of other elements in the window.

Creating new window and assigning this window as parent

self.vtkWidget = QVTKRenderWindowInteractor(self.w_3d)

Using refered window as parent -> leads to floating and overlapping rendered scene

self.vtkWidget = QVTKRenderWindowInteractor(self.w)

import pyqtgraph as pg
import pyqtgraph.opengl as gl
from pyqtgraph.Qt import QtCore, QtGui, QtWidgets
from PyQt5 import Qt
from vtk.qt.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor
import vtk, sys

class GUI:
    def __init__(self):
        self.init_gui() 

    def proxyWidget(self, item, width=None, height=None):
        proxy = QtGui.QGraphicsProxyWidget()
        if(height != None):
            height = item.sizeHint().height() if height==None else height
            item.setMaximumHeight(height)
        if(width!=None):
            width = item.sizeHint().width() if width==None else width
            item.setMaximumWidth(width)
        proxy.setWidget(item)
        return proxy

    def init_gui(self, win_height=800, win_width=1800):
        #self.w = self
        #self.w.scene().sigMouseClicked.connect(self.mousePressEvent) #mouseMoveEvent
        #self.w.scene().sigMouseMoved.connect(self.mouseMoveEvent)
        pg.setConfigOptions(imageAxisOrder='row-major')
        pg.setConfigOption('background', 'w')
        pg.setConfigOption('foreground', 'k')
        self.w = pg.GraphicsWindow(size=(win_width,win_height), border=True)
        self.img = pg.ImageItem()
        self.list_imgs       = QtGui.QListWidget()
        self.btn_Del_Mark    = QtGui.QPushButton('Del Mark')
        self.btn_MarkPed     = QtGui.QPushButton('Mark ped')
        self.lbl_list1       = QtGui.QLabel("List Images")
        self.lbl_list2       = QtGui.QLabel("List Markings")
        self.list_imgs       = QtGui.QListWidget()
        self.list_marks      = QtGui.QListWidget()
        self.layout = pg.GraphicsLayout()
        self.w_3d = pg.GraphicsWindow()
        self.vb = pg.ViewBox()


        self.lbl_list1.setAlignment(QtCore.Qt.AlignCenter)
        self.lbl_list2.setAlignment(QtCore.Qt.AlignCenter)
        self.vb.setAspectLocked()
        self.vb.addItem(self.img)
        self.vb.invertY(True)
        self.vtkWidget = QVTKRenderWindowInteractor(self.w_3d)
        self.w_3d.addItem(self.proxyWidget(self.vtkWidget))

        self.vtkWidget.Initialize()
        self.vtkWidget.Start()
        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.iren.Initialize()
        self.iren.Start()
        self.vtkWidget.show()

        self.layout.addItem(self.vb                             , 1,  3, 20,  20)
        self.layout.addItem(self.proxyWidget(self.lbl_list1     , width=(int(1./10.*win_width)), height=(int(0.9/20.*win_height))),  0,1,1,1)   
        self.layout.addItem(self.proxyWidget(self.lbl_list2     , width=(int(1./10.*win_width)), height=(int(0.9/20.*win_height))),  0,2,1,1)  
        self.layout.addItem(self.proxyWidget(self.list_imgs     , width=(int(1./10.*win_width))),  1,1,20,1)   
        self.layout.addItem(self.proxyWidget(self.list_marks    , width=(int(1./10.*win_width))),  1,2,20,1)   

        self.w.addItem(self.layout)

if __name__ == "__main__":
    app = QtGui.QApplication([])
    guiobj = GUI()

    if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
        QtGui.QApplication.instance().exec_()

EDIT:

Currently I have solved it by having two windows - after several days of failed attempts. But even this looks crap - since the rendered scene floats in the window without reaction to window resize events...

I would like to have those two windows - in one:

One of the failed attempts was as follows - but then pyqt acquires space in the layout without showing the renderer scene in the window... - just empty space:

self.vtkWidget = QVTKRenderWindowInteractor() #No Parent
#...see rest of code in the section above with exception of the following 2 lines
self.layout.addItem(self.proxyWidget(self.vtkWidget), 10, 3, 10, 20)
self.vtkWidget.show()

回答1:


I was able to solve it - I have replaced the QGraphicsLayout with QGridlayout and removed all proxywidget-wrappers and I found a workaround for adding a viewbox by using the plotwidget.

I just need now to remove the axes - but this is secondary

import pyqtgraph as pg
import pyqtgraph.opengl as gl
from pyqtgraph.Qt import QtCore, QtGui, QtWidgets
from PyQt5 import Qt
from vtk.qt.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor
import vtk, sys
import numpy as np
from PIL import Image
class GUI:
    def __init__(self):
        self.init_gui() 

    def proxyWidget(self, item, width=None, height=None):
        proxy = QtGui.QGraphicsProxyWidget()
        if(height != None):
            height = item.sizeHint().height() if height==None else height
            item.setMaximumHeight(height)
        if(width!=None):
            width = item.sizeHint().width() if width==None else width
            item.setMaximumWidth(width)
        proxy.setWidget(item)
        return proxy

    def init_gui(self, win_height=800, win_width=1800):
        pg.setConfigOptions(imageAxisOrder='row-major')
        pg.setConfigOption('background', 'w')
        pg.setConfigOption('foreground', 'k')
        self.w = pg.GraphicsWindow(size=(win_width,win_height), border=True)
        self.img = pg.ImageItem()
        self.list_imgs       = QtGui.QListWidget()
        self.btn_Del_Mark    = QtGui.QPushButton('Del Mark')
        self.btn_MarkPed     = QtGui.QPushButton('Mark ped')
        self.lbl_list1       = QtGui.QLabel("List Images")
        self.lbl_list2       = QtGui.QLabel("List Markings")
        self.list_imgs       = QtGui.QListWidget()
        self.list_marks      = QtGui.QListWidget()
        self.layout = QtGui.QGridLayout()
        self.w.setLayout(self.layout)
        #self.w_3d = pg.GraphicsWindow()

        self.vtkWidget = QVTKRenderWindowInteractor()
        #self.w_3d.addItem(self.proxyWidget(self.vtkWidget))

        self.vtkWidget.Initialize()
        self.vtkWidget.Start()
        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.iren.Initialize()
        self.iren.Start()
        path = "/home/brain/uni/frustum-pointnets/dataset/KITTI/object/testing/image_2/000000.png"
        imgdata = Image.open(path)
        self.imgArr = np.array(imgdata)
        #ToDo: undistort Image if neccessary

        self.img.setImage(self.imgArr)
        #self.vbLayout = self.w.addLayout(row=0,  col=3, rowspan=10,  colspan=20)
        imageGraph = pg.PlotWidget(name='Signalgraph')
        self.vb = imageGraph.plotItem.vb
        self.lbl_list1.setAlignment(QtCore.Qt.AlignCenter)
        self.lbl_list2.setAlignment(QtCore.Qt.AlignCenter)
        self.vb.setAspectLocked()
        self.vb.addItem(self.img)
        self.vb.invertY(True)
        self.vb.setMaximumSize(int(7/10.*win_width), int(9/20.*win_height))
        self.layout.addWidget(imageGraph,                           1 , 3, 10,  20)
        self.layout.addWidget(self.vtkWidget                      , 11, 3, 10,  20)
        self.layout.addWidget(self.lbl_list1 ,                                  0, 1, 1, 1)   
        self.layout.addWidget(self.lbl_list2 ,                                  0, 2, 1, 1)  
        self.layout.addWidget(self.list_imgs ,                                  1, 1, 20,1)   
        self.layout.addWidget(self.list_marks,                                  1, 2, 20,1)   
        sizeHint =  lambda: pg.QtCore.QSize(int(1./10.*win_width), int(0.9/20.*win_height))
        self.lbl_list1.sizeHint = lambda: pg.QtCore.QSize(int(1./10.*win_width), int(0.9/20.*win_height))
        self.lbl_list2.sizeHint = lambda: pg.QtCore.QSize(int(1./10.*win_width), int(0.9/20.*win_height))
        self.list_imgs.sizeHint  = lambda: pg.QtCore.QSize(int(1./10.*win_width), int(18/20.*win_height))
        self.list_marks.sizeHint = lambda: pg.QtCore.QSize(int(1./10.*win_width), int(18/20.*win_height))
        self.list_imgs.setMaximumWidth(int(1./10.*win_width))
        self.list_marks.setMaximumWidth(int(1./10.*win_width))

        self.vtkWidget.show()


if __name__ == "__main__":
    app = QtGui.QApplication([])
    guiobj = GUI()

    if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
        QtGui.QApplication.instance().exec_()


来源:https://stackoverflow.com/questions/57298291/insert-vtk-into-the-right-spot-of-layout

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!