0

我试图了解布局和小部件的嵌套是如何工作的,因此我取出了所有初始化程序参数并使用 .setWhatever、.setParent、.setText 等。除了第二个和第三个 QtWidgets.QVBoxLayout 小部件外,这都有效;对于第一个,它将其父级设置为 frame_main,对于第二个和第三个,它将其设置为 frame_sensor。这两个 frame_ 小部件都是 QtWidgets.QFrame 类型。当第二个和第三个 QVBoxLayout 小部件使用 setParent (frame_sensor) 时,它会生成消息“一个布局只能有另一个布局作为父级”,但是如果我用 QtWidgets.QVBoxLayout (frame_sensor) 实例化该布局小部件,则没有任何抱怨。有人可以解释为什么有时我可以,有时我不能使用 .setParent 或出了什么问题?

import sys
import time

from PyQt6 import QtGui
from PyQt6 import QtWidgets
from PyQt6 import QtCore

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

        self.widgets = { }

        self.frame_main = QtWidgets.QFrame()

        self.frame_main.setParent(self)
        self.frame_main.setObjectName("frame_main")

        self.layout_top = QtWidgets.QVBoxLayout()

        self.layout_top.setParent(self.frame_main)
        self.layout_top.setObjectName("layout_top")

        self.frame_main.setLayout(self.layout_top)

        self.setCentralWidget(self.frame_main)

        self.show()

        self.add_sensor("sensor1", 123)
        self.add_sensor("sensor2", 234)

    def add_sensor(self, sensor, value):
        label_title = QtWidgets.QLabel()

        label_title.setText(sensor)
        label_title.setObjectName("label_title")

        label_value = QtWidgets.QLabel()

        label_value.setText("{:.1f}".format(float(value)))
        label_value.setObjectName("label_value")

        frame_sensor = QtWidgets.QFrame()

        frame_sensor.setObjectName("frame_sensor")
        frame_sensor.setStyleSheet("border: 2px solid;")

        # also makes frame_sensor the child of frame_main
        self.layout_top.addWidget(frame_sensor)

        # this works
        #layout_vbox = QtWidgets.QVBoxLayout(frame_sensor)

        # this doesn't work
        layout_vbox = QtWidgets.QVBoxLayout()
        layout_vbox.setParent(frame_sensor)

        layout_vbox.setObjectName("layout_vbox")
    
        layout_vbox.addWidget(label_title)
        layout_vbox.addWidget(label_value)

        self.widgets.update({ sensor : label_value })

    def closeEvent(self, event):
        event.accept()
        sys.exit()

if __name__ == '__main__':
    app = QtWidgets.QApplication([])
    window = MainWindow()

    app.exec()
4

1 回答 1

2

没有文档表明其目标之一setParent()是建立一个小部件,布局将处理其子项的几何形状。如果你想这样做,有 2 个选项:

  • 在布局构造函数中指出它。
layout_vbox = QtWidgets.QVBoxLayout(frame_sensor)
  • 或者使用 QWidget 的 setLayout 方法。
layout_vbox = QtWidgets.QVBoxLayout()
frame_sensor.setLayout(layout_vbox)

的目标setParent()是在 QObjects 之间建立一个层次结构,以便能够处理孩子的内存(所有权),因为 Qt 实现了在堆中创建对象。所以逻辑是如果父亲从记忆中删除,那么他首先也会从记忆中删除孩子。因此,例如,一个窗口被消除,窗口的所有组件也将被消除,即使它们不是它的直接子级。

从上面可以得出结论,目标是 QObjects,但是使用该逻辑 QWidget 也使用该层次结构进行绘制。

支持我的回答的另一个论点是该setParent()方法需要一个 QObject,而不是 QWidget:所有 QWidget 都是 QObject,但并非所有 QObject 都是 QWidget-

于 2021-04-28T21:16:21.027 回答