我有一个我需要重新创建的小部件。我在下面做了大量简化的例子。在示例中,我想使用新属性重新创建窗口小部件。我知道在这个例子中我可以使用QtGui.QLabel.setText()
,但是我不能在真实程序中做同样的事情。
以下是示例:
from PyQt4 import QtGui
import sys
class MainWindow(QtGui.QWidget):
def __init__(self):
super().__init__()
self.initAttributes()
self.initLabel()
self.initUI()
def initAttributes(self):
self.text = 'initial text'
def initLabel(self):
self.label = QtGui.QLabel()
self.label.setText(self.text)
def changeText(self):
self.text = 'different text'
self.initLabel()
self.initUI()
def initUI(self):
button = QtGui.QPushButton()
button.clicked.connect(self.changeText)
grid = QtGui.QGridLayout()
grid.addWidget(self.label)
grid.addWidget(button)
self.setLayout(grid)
self.show()
app = QtGui.QApplication(sys.argv)
window = MainWindow()
app.exec_()
我在这里尝试做的是制作一个具有一些初始属性的小部件,在本例中是一个带有文本'initial text'
的标签。如前所述,我不是要尝试更改属性,我尝试使用属于窗口对象的属性中的新对象重新创建对象。
按钮背后的想法是,当按下时,它将改变窗口的自我文本'属性为其他内容,并尝试重新创建标签,使用与之前相同的方法initLabel
。
结果应该是窗口重新初始化,重新创建的标签将包含新文本'different text'
。然而,没有任何事情发生。
修改
解决方案是,对于同一个小部件,setLayout
不能被调用两次。在Schollii的链接答案中使用小部件重置技术时,它可以正常工作。下面是修改后的工作函数(而不是再次转储整个代码)
def changeText(self):
self.text = 'different text'
self.initLabel()
self.delLayout()
self.initUI()
def delLayout(self):
QtGui.QWidget().setLayout(self.layout())
答案 0 :(得分:2)
在您的代码中,当您单击按钮时,您正在执行相应的操作:
def changeText(self):
self.text = 'different text'
self.label = QtGui.QLabel(self.text)
self.initUI()
这会创建新标签,并重新进入UI(重复信号连接,创建小部件,设置布局等)。
如果要重新创建标签而不是设置文本,则不应重新初始化UI。相反,您应该只删除从布局中重新创建的项目并重新添加它们。示例:
self.layout().removeWidget(self.label)
self.text = 'new text'
self.label = QtGui.QLabel(self.text)
self.layout().addWidget(self.label, 0, 0)
如果您想要重新创建整个小部件,则应清除其所有布局的项目,或者使用新的空白替换布局,如此SO帖子replacing layout on a QWidget with another layout中所述(您不能这样做)不止一次致电setLayout()
,但您可以转移布局!)。
答案 1 :(得分:0)
您的示例失败,因为如果已经有QMainWindow
,则无法设置{{1}}的布局。
如果运行带有可见终端的示例代码,则在单击按钮时会看到下面的错误。
QWidget :: setLayout:尝试在MainWindow上设置QLayout“”,已经有布局
理论上,您应该能够删除旧布局,并添加一个新布局,但在PyQt中看起来很难。 (编辑:请参阅Schollii关于如何删除和重新添加布局的答案)
我建议您查看是否确实需要重新创建整个布局,或者是否只需要替换布局中的小部件。如果您决定后者,那么在布局中删除/替换小部件时会有大量的stackoverflow帖子。