QLayout.replace 不替换

QLayout.replace not replacing

每次单击按钮 (self.btn) 时,我都有以下代码 替换 小部件 (self.lbl):

import sys
from PySide2.QtCore import Slot
from PySide2.QtWidgets import QApplication, QLabel, QVBoxLayout, QWidget, \
        QPushButton


class Workshop(QWidget):

    def __init__(self):
        super().__init__()
        self.n = 0
        self.btn = QPushButton('Push me')
        self.lbl = QLabel(str(self.n))

        self.main_layout = QVBoxLayout()
        self.sub_layout = QVBoxLayout()
        self.sub_layout.addWidget(self.lbl)
        self.sub_layout.addWidget(self.btn)
        self.main_layout.addLayout(self.sub_layout)

        self.btn.clicked.connect(self.change_label)
        self.setLayout(self.main_layout)
        self.show()

    @Slot()
    def change_label(self):
        new_label = QLabel(str(self.n + 1))
        self.main_layout.replaceWidget(self.lbl, new_label)
        self.n += 1
        self.lbl = new_label


if __name__ == '__main__':
    app = QApplication()

    w = Workshop()

    sys.exit(app.exec_())

初始化后,对象 w 看起来像这样:

当我点击“推送我”按钮 (self.btn) 时,数字会根据需要递增,但初始的“0”仍保留在后台:

但是其他号码并没有留在后台;只有“0”会。例如,这里是“22”(我点击“推我”22次后的结果):

注意: 知道我可以用setText方法得到我想要的结果,但这段代码只是我将针对 class 改编的一个片段,其中我不会有像 setText.

这样的方法

谢谢!

当您替换布局中的小部件时,之前的小部件仍然存在。
来自 replaceWidget():

The parent of widget from is left unchanged.

问题是,当从布局中删除小部件时,它仍然保留其父级(在您的情况下,Workshop 实例),因此您仍然可以查看它。如果为您创建的每个新 QLabel 将对齐设置为 AlignCenter,这会更清楚:您会看到,如果您添加一个新标签并调整 window 的大小,前一个将保持其先前的位置:

class Workshop(QWidget):

    def __init__(self):
        # ...
        self.lbl = QLabel(str(self.n), alignment=QtCore.Qt.AlignCenter)
        # ...

    def change_label(self):
        new_label = QLabel(str(self.n + 1), alignment=QtCore.Qt.AlignCenter)
        # ...

你有两种可能,其实很相似:

  • 将“已删除”小部件的父级设置为 None:垃圾收集器将在您覆盖后立即删除小部件 self.lbl:
    self.lbl.setParent(None)
  • 通过调用 deleteLater() 删除小部件,这是将小部件重新设置为 None 时发生的情况,如果它没有其他持久引用,则会被垃圾收集:
    self.lbl.deleteLater()

对于你的目的,我建议你使用 deleteLater(),因为调用 setParent()(这是 QObject 的 setParent 的重新实现)实际上做了很多其他事情(最重要的是,检查焦点链并重置小部件的 window 标志),并且由于小部件无论如何都会被删除,所有这些实际上都是不必要的,QObject 的 setParent(None) 实现无论如何都会被调用。

您遇到的图形“故障”可能取决于底层的低级绘画功能,在某些情况下,它在 MacOS 上有一些(已知的)意外行为。