简体   繁体   English

PyQt6 对嵌套布局或小部件感到困惑

[英]PyQt6 confused about nesting layouts or widgets

I'm trying to understand how nesting of layouts and widgets work so I took out all of the initializer arguments and used.setWhatever instead, .setParent, .setText, and so on.我试图了解布局和小部件的嵌套是如何工作的,因此我取出了所有初始化程序 arguments 并使用了.setWhatever、.setParent、.setText 等等。 This worked except for the second and third of the QtWidgets.QVBoxLayout widgets;除了第二个和第三个 QtWidgets.QVBoxLayout 小部件外,这都有效; for the first one it's setting its parent to frame_main, and for the second and third ones it's setting it to frame_sensor.对于第一个,它将其父级设置为 frame_main,对于第二个和第三个,它将其设置为 frame_sensor。 Both of those frame_ widgets are of type QtWidgets.QFrame.这两个 frame_ 小部件都是 QtWidgets.QFrame 类型。 When the second and third QVBoxLayout widgets use setParent (frame_sensor) it produces the message "A layout can only have another layout as a parent" but if I instantiate that layout widget with QtWidgets.QVBoxLayout (frame_sensor) there's no complaint.当第二个和第三个 QVBoxLayout 小部件使用 setParent (frame_sensor) 时,它会生成消息“一个布局只能有另一个布局作为父级”,但是如果我用 QtWidgets.QVBoxLayout (frame_sensor) 实例化该布局小部件,则没有任何抱怨。 Can someone explain why sometimes I can and sometimes I can't use.setParent or what's going wrong?有人可以解释为什么有时我可以,有时我不能使用.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()

There is no documentation that indicates one of the objectives of setParent() is to establish a widget to which the layout will handle the geometry of its children.没有文档表明setParent()的目标之一是建立一个小部件,布局将处理其子项的几何形状。 If you want to do this there are 2 options:如果你想这样做,有 2 个选项:

  • Indicate it in the layout constructor.在布局构造函数中指出它。
layout_vbox = QtWidgets.QVBoxLayout(frame_sensor)
  • Or use the QWidget's setLayout method.或者使用 QWidget 的 setLayout 方法。
layout_vbox = QtWidgets.QVBoxLayout()
frame_sensor.setLayout(layout_vbox)

The objective of setParent() is to establish a hierarchy between the QObjects to be able to handle the memory of the children (the ownership) since Qt implements the creation of objects in the heap. setParent()的目标是在 QObjects 之间建立层次结构,以便能够处理子代(所有权)的 memory,因为 Qt 实现了在堆中创建对象。 So the logic is if the father is removed from memory then first he will remove the children from it as well.所以逻辑是如果父亲从 memory 中删除,那么首先他也会从其中删除孩子。 Thus, for example, a window is eliminated, all the components of the window will also be eliminated, even if they are not the direct children of it.因此,例如,一个 window 被消除,window 的所有组件也将被消除,即使它们不是它的直接子代。

From the above it is concluded that the objective is the QObjects, but using that logic the QWidget also use that hierarchy for painting.从上面可以得出结论,目标是 QObjects,但是使用该逻辑 QWidget 也使用该层次结构进行绘制。

Another argument in favor of my answer is that the setParent() method expects a QObject, not a QWidget: All QWidget is a QObject but not all QObject is a QWidget-支持我的答案的另一个论点是setParent()方法需要一个 QObject,而不是 QWidget:所有 QWidget 都是 QObject 但并非所有 QObject 都是 QWidget-

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM