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 上有一些(已知的)意外行为。
每次单击按钮 (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 上有一些(已知的)意外行为。