使用QLayout将我的小部件安排在彼此相邻的较大窗口时,我遇到了对象引用问题。
我有以下情况
class MyClass(QObject):
widgetCollection = []
def spawn(self):
widget = MyQWidget() #containing a QLineWidget called "nameEdit"
self.widgetCollection.append(widget)
self._window = QtGui.QWidget()
layout = QtGui.QHBoxLayout()
listView = QtGui.QListWidget()
for equation in self.wigdetCollection:
equationName = equation.nameEdit.text()
item = QtGui.QListWidgetItem(equationName)
listView.addItem(item)
layout.addWidget(listView)
layout.addWidget(widget)
self._window.setWindowTitle("Equation Editor")
self._window.setLayout(layout)
self._window.show()
def respawn(self):
self.spawn()
每次调用spawn()时,我都想在集合中添加一个新的小部件。另外,我想打开一个新窗口,其中有一个ListView,左边是所有窗口小部件名,右边是新创建的窗口小部件。
现在第一次调用spawn() - 方法就像预期的那样工作。但第二个电话会抛出一个例子:
equationName = widget.nameEdit.text()
RuntimeError: wrapped C/C++ object of type QLineEdit has been deleted
我认为它与行
有关layout.addWidget(widget)
我已经读过某个地方,当作为项添加时,布局取得了小部件的所有权。一旦我超出布局参考的范围(在这种情况下是本地的),我就松开了小部件。所以我的集合中的widget-item似乎也被删除了。
有人可以帮忙吗?我该如何防止这种情况。
答案 0 :(得分:1)
问题是每次spawn()关闭时都会替换self._window:Python会丢弃旧的窗口小部件,而self._window会引用一个新的QWidget实例。由于旧的窗口小部件是列表视图和qlineedit小部件的父级(在代码中称为 - 容易混淆 - 只是"小部件"),这些将在Qt意义上被销毁 - 即他们的C ++部分将被销毁。列表视图不会在显示的代码中的任何其他位置引用,因此列表视图的Python部分也将被销毁,这就是应该的方式。
但是,qlineedit在类范围的注册表(widgetCollection)中引用,因此qlineedit的Python部分不会被销毁。这意味着每次调用spawn()时,QLineEdit的前一个实例(通过类范围的widgetCollection中的MyQWidget)变成一个僵尸:它在C ++ Qt级别死了,但它仍处于Python级别。仍然可以访问僵尸的方法,但在许多情况下,您将看到有关C / C ++的Qt错误已被删除,并且您可能会遇到崩溃或其他未定义的行为。
从发布的代码中不清楚widgetCollection的意图是什么,但由于附加的上一项将在spawn()期间变为僵尸,widgetCollection如图所示无用。问题的解决方案取决于有关如何使用集合的详细信息,但由于可以假设集合有目的,因此问题是窗口小部件的替换:也许小部件集合应该是窗口集合,然后当self._window被替换,前一个窗口保持活动状态,因此子窗口小部件也可以保持活动状态。
答案 1 :(得分:-1)
我自己解决了: - )
我对spawn()方法的初始调用是这样的:
mc = MyClass()
mc.spawn()
第一个好的。现在我想在inst1
内生成另一个。为此,我使用了
self.spawn()
在respawn()
- 抛出上述错误的方法。
必须是以下
def respawn(self):
mc = MyClass()
mc.spawn()
我必须创建另一个MyClass
实例,与所有其他实例共享widgetCollection
。根据需要......