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 保持活动状态,因此子部件也保持活动状态。