【发布时间】:2019-12-09 10:01:32
【问题描述】:
我正在尝试将 VTK 3D 场景小部件放入 pyqtgraphics.GraphicsLayout() 的正确位置。但是,如果我没有将窗口指定为父窗口,或者如果我这样做,场景不会出现 - 场景不适应空闲区域,它只是漂浮在左上角。
我目前正在努力寻找将视图框和 vtkrenderer 放入同一窗口的解决方案。
我的一个尝试是分配 self.w(请参阅本段下方) - 这是我作为渲染器父级的主窗口,但我不知道如何告诉渲染器将自己放置在较低的窗口的右上角而不是浮动在左上角 - 这也会导致窗口中的其他元素重叠。
创建新窗口并将此窗口指定为父窗口
self.vtkWidget = QVTKRenderWindowInteractor(self.w_3d)
使用引用窗口作为父窗口 -> 导致渲染场景浮动和重叠
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_()
编辑:
目前我已经通过有两个窗口解决了这个问题 - 经过几天的失败尝试。但即使这样看起来也很糟糕——因为渲染的场景漂浮在窗口中,对窗口大小调整事件没有反应......
我希望将这两个窗口合二为一:
其中一个失败的尝试如下 - 但随后 pyqt 在布局中获取空间而没有在窗口中显示渲染器场景...... - 只是空白:
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()
【问题讨论】:
-
好吧,也许它只是我,但看起来好像你在这里有一种循环引用——vtkWidget 依赖于 w-3d,它依赖于 layout_3d,它依赖于 vtkWidget ?这可能是为什么它不能按预期工作的问题的一部分。那么先有鸡还是先有蛋?
-
@DennisJensen 是的,但是 - 在本例中,它们是两个单独的窗口 - 但问题是 - 我不能将 layout_3d 作为父级分发 - 因为它不接受 graphicslayout 类的对象 - 所以我接受不知道如何解决这个问题...
-
@DennisJensen 我无论如何都希望在一个窗口中拥有所有小部件.. :/
-
我确信有办法做到这一点,但我现在没有时间查看它。我认为您仍然需要改写您的问题-至少更详细地概述您的问题完全是什么-因为我认为循环引用根本无法正常工作
-
@DennisJensen 好的,我现在就做 - 因为我已经工作了好几天了 - 我仍然不知道 - 为什么不工作......如果我将小部件直接插入layout.addItem(...) 的布局并且没有绕过 vtkwidget 的父级 - 它根本不会出现在窗口中
标签: python qt pyqt vtk qt-designer