QLayout Additem - 防止所有权转移
QLayout Additem - prevent transfer of ownership
当我使用 QLayout 将我的小部件排列在更大的 window 上并排放置时,object 引用出现问题。
我有以下情况
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() 时,我都想向 collection 添加一个新的小部件。此外,我想打开一个新的 window,其中有一个 ListView,左侧是所有小部件名称,右侧是新创建的小部件。
现在,对 spawn() 方法的第一次调用按预期工作。但是第二次调用抛出异常:
equationName = widget.nameEdit.text()
RuntimeError: wrapped C/C++ object of type QLineEdit has been deleted
我觉得跟线有关系
layout.addWidget(widget)
我在某处读到,布局在添加为项目时拥有小部件的所有权。一旦我超出 layout-reference 的范围(在本例中是本地的),我就会松开小部件。所以我的 collection 中的 widget-item 似乎也被删除了。
有人可以帮忙吗?我该如何防止这种情况。
自己解决了:-)
我最初调用 spawn() 方法是这样的:
mc = MyClass()
mc.spawn()
第一个没问题。现在我想从 inst1
中生成另一个。为此,我使用了
self.spawn()
在 respawn()
方法中抛出上述错误。
必须是下面的
def respawn(self):
mc = MyClass()
mc.spawn()
我必须创建另一个 MyClass
实例,它与所有其他实例共享 widgetCollection
。随心所欲....
问题是每次 spawn() 关闭时 self._window 都会被替换:Python 丢弃旧的 window 小部件,并且 self._window 引用一个新的 QWidget 实例。由于旧的 window 小部件是列表视图和 qlineedit 小部件的父级(在代码中称为 - 令人困惑 - 只是 "widget"),这些将在术语的 Qt 意义上被破坏 - 即他们的 C++ 部分将被破坏。显示代码中的其他任何地方都没有引用列表视图,因此列表视图的 Python 部分也将被销毁,这是应该的方式。
但是,qlineedit 在 class 范围的注册表 (widgetCollection) 中被引用,因此 qlineedit 的 Python 部分不会被破坏。这意味着每次调用 spawn() 时,QLineEdit 的前一个实例(通过 class-widgetCollection 中的 MyQWidget)变成僵尸:它在 C++ Qt 级别已死,但在 Python级。仍然可以访问僵尸的方法,但在许多情况下,您会看到有关 C/C++ 已被删除的 Qt 错误,并且您可能会遇到崩溃或其他未定义的行为。
从发布的代码中不清楚 widgetCollection 的用途是什么,但是由于之前附加的项目将在 spawn() 期间变成僵尸,widgetCollection 如图所示是无用的。问题的解决方案取决于有关如何使用集合的详细信息,但既然可以假设集合是有目的的,那么问题就是 window 小部件的替换:也许小部件集合应该是 window 集合,然后当 self._window 被替换时,之前的 window 保持活动状态,因此子部件也保持活动状态。
当我使用 QLayout 将我的小部件排列在更大的 window 上并排放置时,object 引用出现问题。
我有以下情况
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() 时,我都想向 collection 添加一个新的小部件。此外,我想打开一个新的 window,其中有一个 ListView,左侧是所有小部件名称,右侧是新创建的小部件。
现在,对 spawn() 方法的第一次调用按预期工作。但是第二次调用抛出异常:
equationName = widget.nameEdit.text()
RuntimeError: wrapped C/C++ object of type QLineEdit has been deleted
我觉得跟线有关系
layout.addWidget(widget)
我在某处读到,布局在添加为项目时拥有小部件的所有权。一旦我超出 layout-reference 的范围(在本例中是本地的),我就会松开小部件。所以我的 collection 中的 widget-item 似乎也被删除了。
有人可以帮忙吗?我该如何防止这种情况。
自己解决了:-)
我最初调用 spawn() 方法是这样的:
mc = MyClass()
mc.spawn()
第一个没问题。现在我想从 inst1
中生成另一个。为此,我使用了
self.spawn()
在 respawn()
方法中抛出上述错误。
必须是下面的
def respawn(self):
mc = MyClass()
mc.spawn()
我必须创建另一个 MyClass
实例,它与所有其他实例共享 widgetCollection
。随心所欲....
问题是每次 spawn() 关闭时 self._window 都会被替换:Python 丢弃旧的 window 小部件,并且 self._window 引用一个新的 QWidget 实例。由于旧的 window 小部件是列表视图和 qlineedit 小部件的父级(在代码中称为 - 令人困惑 - 只是 "widget"),这些将在术语的 Qt 意义上被破坏 - 即他们的 C++ 部分将被破坏。显示代码中的其他任何地方都没有引用列表视图,因此列表视图的 Python 部分也将被销毁,这是应该的方式。
但是,qlineedit 在 class 范围的注册表 (widgetCollection) 中被引用,因此 qlineedit 的 Python 部分不会被破坏。这意味着每次调用 spawn() 时,QLineEdit 的前一个实例(通过 class-widgetCollection 中的 MyQWidget)变成僵尸:它在 C++ Qt 级别已死,但在 Python级。仍然可以访问僵尸的方法,但在许多情况下,您会看到有关 C/C++ 已被删除的 Qt 错误,并且您可能会遇到崩溃或其他未定义的行为。
从发布的代码中不清楚 widgetCollection 的用途是什么,但是由于之前附加的项目将在 spawn() 期间变成僵尸,widgetCollection 如图所示是无用的。问题的解决方案取决于有关如何使用集合的详细信息,但既然可以假设集合是有目的的,那么问题就是 window 小部件的替换:也许小部件集合应该是 window 集合,然后当 self._window 被替换时,之前的 window 保持活动状态,因此子部件也保持活动状态。