PYQT5设计器,是否格式化了GUI?背景和面板[关闭]

问题描述 投票:0回答:1
我只是学习如何使用PYQT5 Designer for Python设计GUI,但遇到了一些问题。我想按照这张惊人的图纸设计一些东西

“”

我想让框架或小部件在背景(蓝色)中实时绘制数据,该数据覆盖整个窗口,并在顶部带有按钮和/或其他对象的浮动“面板”。这些面板必须卡在侧面。在上图中,我希望将面板1捕捉到程序的左侧,将面板2捕捉到程序的底部,将面板3捕捉到程序的右侧。另外,面板2必须居中,但我想我已经涵盖了那个。

我将如何去做?我可以将网格放置在网格顶部还是将框架放置在框架顶部?

python grid widget pyqt5 designer
1个回答
0
投票
QMainWindow提供了四个“区域”,您可以在其中放置QDockWidget

Qt main window areas

不幸的是,这些小部件将始终占据放置它们的一侧的整个区域。

虽然有一个“ hack”允许您执行此操作,但我不能保证它可以无缝运行。

它通过调整坞站小部件

和中央小部件的大小来工作,因此坞站将仅使用所需的空间并相应地移动,同时将中央小部件的几何形状设置为整个可用区域。

考虑到,由于resizeEvent可能在某个时间点发生[[之前,窗口被“映射”了(当窗口实际上对用户变为[[可见时)),我们需要一个小技巧来确保应用了几何正确地。这是在paint事件中完成的(我要警告您,这是

not一个非常干净的方法),并且每当它检测到其中一个底座没有正确放置时,它将尝试再次调整它们的大小。 。 重要检查调整大小必须在绘画事件中发生(这就是为什么使用QTimer延迟它们的原因)。

请注意,为确保坞站小部件的大小正确,您可能需要为坞站或其某些子项设置最小(或最大)大小。另外,所有底座都将autoFillBackground属性设置为True,因此其背景将不会显示中央小部件。class DockTest(QtWidgets.QMainWindow): def __init__(self): super().__init__() uic.loadUi('docktest.ui', self) def checkGeometries(self): central = self.centralWidget().geometry() for dock in self.findChildren(QtWidgets.QDockWidget): if dock.parent() != self: continue area = self.dockWidgetArea(dock) if ((area == QtCore.Qt.LeftDockWidgetArea and central.x() > dock.geometry().x()) or (area == QtCore.Qt.TopDockWidgetArea and central.y() > dock.geometry().y()) or (area == QtCore.Qt.RightDockWidgetArea and central.right() < dock.geometry().right()) or (area == QtCore.Qt.BottomDockWidgetArea and central.bottom() > dock.geometry().bottom())): self.resizeWidgets() return def resizeWidgets(self): # give Qt some time for layout adjustments QtWidgets.QApplication.processEvents() geometry = self.centralWidget().geometry() left = top = right = bottom = None for dock in self.findChildren(QtWidgets.QDockWidget): if dock.parent() != self: continue area = self.dockWidgetArea(dock) if area == QtCore.Qt.LeftDockWidgetArea: left = dock geometry.setLeft(left.geometry().x()) elif area == QtCore.Qt.TopDockWidgetArea: top = dock geometry.setTop(top.geometry().y()) elif area == QtCore.Qt.RightDockWidgetArea: right = dock geometry.setRight(right.geometry().right()) elif area == QtCore.Qt.BottomDockWidgetArea: bottom = dock geometry.setBottom(bottom.geometry().bottom()) if not dock.titleBarWidget(): # set a fake title bar widget to avoid drawing margins titleWidget = QtWidgets.QWidget() # the following could change according to the current style margin = dock.layout().contentsMargins().top() titleWidget.sizeHint = titleWidget.minimumSizeHint = lambda: QtCore.QSize(margin, margin) dock.setTitleBarWidget(titleWidget) # ensure that the dock is not movable, floatable or closable if dock.features() & (dock.DockWidgetMovable | dock.DockWidgetFloatable | dock.DockWidgetClosable): dock.setFeatures(dock.features() & ~(dock.DockWidgetMovable | dock.DockWidgetFloatable) | dock.DockWidgetClosable) # set the central widget geometry to the full available area self.centralWidget().setGeometry(geometry) # update the geometry for each dock widget, according to its position if left: dockGeo = left.geometry() dockGeo.setHeight(left.sizeHint().height()) dockGeo.moveTop(geometry.center().y() - dockGeo.height() / 2) left.setGeometry(dockGeo) if top: dockGeo = top.geometry() dockGeo.setWidth(top.minimumSizeHint().width()) dockGeo.moveLeft(geometry.center().x() - dockGeo.width() / 2) top.setGeometry(dockGeo) if right: dockGeo = right.geometry() dockGeo.setHeight(right.minimumSizeHint().height()) dockGeo.moveTop(geometry.center().y() - dockGeo.height() / 2) right.setGeometry(dockGeo) if bottom: dockGeo = bottom.geometry() dockGeo.setWidth(bottom.minimumSizeHint().width()) dockGeo.moveLeft(geometry.center().x() - dockGeo.width() / 2) bottom.setGeometry(dockGeo) def resizeEvent(self, event): super().resizeEvent(event) self.resizeWidgets() def showEvent(self, event): super().showEvent(event) self.resizeWidgets() def paintEvent(self, event): super().paintEvent(event) # IMPORTANT! the checking (and eventual resizing) mus NOT # happen within a paintEvent, so we delay that QtCore.QTimer.singleShot(0, self.checkGeometries) 不过,更好(或更简单)的方法是只创建自己的“停靠小部件”(它们是简单的QWidget),并确保将主窗口设置为其父窗口。这种方法的缺点是您不能使用设计器将这些小部件添加到主窗口中(但是您可以使用它来单独创建它们),而必须通过代码将其添加。

在下面的示例中,我用代码创建了所有内容,但是您可以使用QWidget子类来创建它们,并使用self.leftWidget = MyLeftDock(self)之类的东西进行添加。

class SimpleDock(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()

        self.setCentralWidget(QtWidgets.QLabel('Child test', alignment=QtCore.Qt.AlignCenter))
        self.centralWidget().setStyleSheet('background: rgb(153, 217, 234);')

        self.leftWidget = QtWidgets.QWidget(self)
        leftLayout = QtWidgets.QVBoxLayout(self.leftWidget)
        for i in range(4):
            leftLayout.addWidget(QtWidgets.QPushButton('button'))
        self.leftWidget.setAutoFillBackground(True)

        self.bottomWidget = QtWidgets.QWidget(self)
        bottomLayout = QtWidgets.QGridLayout(self.bottomWidget)
        for r in range(2):
            slider = QtWidgets.QSlider(QtCore.Qt.Horizontal)
            slider.setMinimumWidth(300)
            bottomLayout.addWidget(slider, r, 0)
            bottomLayout.addWidget(QtWidgets.QToolButton(), r, 1)
        self.bottomWidget.setAutoFillBackground(True)

        self.rightWidget = QtWidgets.QWidget(self)
        rightLayout = QtWidgets.QVBoxLayout(self.rightWidget)
        frame = QtWidgets.QFrame()
        frame.setMinimumSize(48, 48)
        frame.setFrameStyle(frame.StyledPanel|frame.Raised)
        rightLayout.addWidget(frame)
        rightLayout.addWidget(QtWidgets.QLabel(
            'Some text'))
        self.rightWidget.setAutoFillBackground(True)

    def resizeWidgets(self):
        QtWidgets.QApplication.processEvents()
        geometry = self.centralWidget().geometry()

        leftGeo = self.leftWidget.geometry()
        leftGeo.setSize(self.leftWidget.sizeHint())
        leftGeo.moveTop(geometry.center().y() - leftGeo.height() / 2)
        self.leftWidget.setGeometry(leftGeo)

        bottomGeo = self.bottomWidget.geometry()
        bottomGeo.setSize(self.bottomWidget.sizeHint())
        bottomGeo.moveCenter(geometry.center())
        bottomGeo.moveBottom(geometry.bottom())
        self.bottomWidget.setGeometry(bottomGeo)

        rightGeo = self.rightWidget.geometry()
        rightGeo.setSize(self.rightWidget.sizeHint())
        rightGeo.moveCenter(geometry.center())
        rightGeo.moveRight(geometry.right())
        self.rightWidget.setGeometry(rightGeo)

    def resizeEvent(self, event):
        super().resizeEvent(event)
        self.resizeWidgets()

这是一个比较(两者之间当然会有一些细微的差异,因为两者都是使用不同的方法创建的,但这仅是示例):

dock test comparison

© www.soinside.com 2019 - 2024. All rights reserved.