为什么小部件在 OOP 版本中重叠

Why widgets overlaps in the OOP version

我将我的情况简化为一个简单的情况:我想在 PyQt5 中编写 GUI,其中有一个名为 grid 的主要 QGridLayout,其中有另一个网格 gridParamter和一个 QListView 小部件。 gridParamter中有2个QLabel

这是代码

import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

def window():
    app = QApplication(sys.argv)
    win = QWidget()

    list1 = QListView()

    gridParameter = QGridLayout()

    idxRow = 0
    label_1 = QLabel("I am label one")
    gridParameter.addWidget(label_1, idxRow, 0)

    idxRow = 1
    label_2 = QLabel("I am label two")
    gridParameter.addWidget(label_2, idxRow, 1)

    grid = QGridLayout()
    grid.addLayout(gridParameter, 0, 0)
    grid.setSpacing(2)
    grid.addWidget(list1)

    win.setLayout(grid)
    win.show()
    sys.exit(app.exec_())

if __name__ == '__main__':      
    window()

可以按照我的预期生成GUI。但是当我尝试以 OOP 风格重写它时,即

import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *


class MainWindow(QWidget):
    def __init__(self):
        QWidget.__init__(self)

        list1 = QListView(self)

        gridParameter = QGridLayout(self)

        idxRow = 0
        label_1 = QLabel("I am label one", self)
        gridParameter.addWidget(label_1, idxRow, 0)

        idxRow = 1
        label_2 = QLabel("I am label two", self)
        gridParameter.addWidget(label_2, idxRow, 1)

        grid = QGridLayout(self)
        grid.addLayout(gridParameter, 0, 0)
        grid.setSpacing(2)
        grid.addWidget(list1)

        self.setLayout(grid)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    mainWin = MainWindow()
    mainWin.show()
    sys.exit( app.exec_() )

我发现 label_1list1 重叠,当我尝试调整主要 windows 的大小时,list1 总是占据网格位置 (0, 0 ).

首先你必须了解以下内容:

  1. 请记住以下表达式:

    lay = FooLayout()
    some_widget.setWidget(lay)
    

相当于:

lay = FooLayout(some_widget)

这两者都表明布局将处理子项的几何形状。

  1. 另一方面,如果一个小部件已经有一个布局,除非删除以前的布局,否则无法建立其他布局。

因此,在您的情况下,只有第一条指令起作用,而接下来的两条指令不起作用,因此布局网格将被消除,列表视图仅保留,因为它是小部件的子项。

gridParameter = QGridLayout(self)
# ...
grid = QGridLayout(self)
# ...
self.setLayout(grid)

在我的例子中,我避免放置小部件的父级以查看是否存在问题,而且我仅在必要时才建立为布局的父级:

import sys
from PyQt5 import QtCore, QtGui, QtWidgets


class MainWindow(QtWidgets.QWidget):
    def __init__(self):
        super(MainWindow, self).__init__()

        list1 = QtWidgets.QListView()

        gridParameter = QtWidgets.QGridLayout()

        idxRow = 0
        label_1 = QtWidgets.QLabel("I am label one")
        gridParameter.addWidget(label_1, idxRow, 0)

        idxRow = 1
        label_2 = QtWidgets.QLabel("I am label two")
        gridParameter.addWidget(label_2, idxRow, 1)

        grid = QtWidgets.QGridLayout(self) # <--- principal layout
        grid.addLayout(gridParameter, 0, 0)
        grid.setSpacing(2)
        grid.addWidget(list1)


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    mainWin = MainWindow()
    mainWin.show()
    sys.exit(app.exec_())

总之,必要时使用self