【问题标题】:PyQt6 confused about nesting layouts or widgetsPyQt6 对嵌套布局或小部件感到困惑
【发布时间】:2021-04-28 20:51:30
【问题描述】:

我试图了解布局和小部件的嵌套是如何工作的,因此我取出了所有初始化程序参数并改用 .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()

【问题讨论】:

标签: python pyqt pyqt6


【解决方案1】:

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

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

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-08-14
    • 2017-05-10
    • 1970-01-01
    • 1970-01-01
    • 2016-04-08
    • 2012-09-21
    • 2011-02-04
    • 1970-01-01
    相关资源
    最近更新 更多