【问题标题】:PySide Error: "Internal C++ object [..] already deleted."; While recursive grab/create QObjectsPySide 错误:“内部 C++ 对象 [..] 已删除。”;递归抓取/创建 QObjects
【发布时间】:2015-03-21 00:44:00
【问题描述】:

我对 PySide 及其内部清理过程有一些问题。我的 PySide 对象似乎在我真正使用它们之前就被删除了。以下示例可能不是最好的示例,但最简单的示例是简单地重现相同的错误。唯一的区别是,在我使用的应用程序中,API 给了我一个wrapInstance 函数来获取QMainWindow(每次都有一个新的ID)。但是错误是一样的。

import sys
from PySide import QtGui


class AnyApplication(QtGui.QMainWindow):

    def __init__(self):
        super(AnyApplication, self).__init__()
        self.initUI()

    def initUI(self):
        self._menuBar = self.menuBar()
        for dummy in ["File","Edit","Help"]:
            self._menuBar.addMenu(dummy)
        self.setGeometry(300, 300, 250, 150)
        self.setWindowTitle('MenuTest')    

class MenuBar(object):

    def __init__(self, qMenuBar):
        self.menuBar = qMenuBar

    def AddMenu(self, name):
        result = self.GetMenu(name)
        if result: return result
        else:
            new = self.menuBar.addMenu(name)
            print "Created: ",name , new
            result = Menu(new, name)
        return result

    def GetMenu(self, name):
        print "\nSearch for: ",name
        for action in self.menuBar.actions():
            if action.text()==name:
                print "Found: ",name , action.menu().actions()
                return Menu( action.menu(), name)
        return None

class Menu(object):
    def __init__(self, menu=None, name=None):
        self.menu   = menu
        self.name   = name

    def AddMenu(self, name):
        # print "Name: ",name
        result = self.GetMenu(name)
        if result: return result
        else:
            new = self.menu.addMenu(name)
            print "Created: ",name , new
            result = Menu(new, name)
        return result

    def GetMenu(self, name):
        print "\nSearch for: ",name
        for action in self.menu.actions():
            if action.text()==name:
                print "Found: ",name , action.menu()
                return Menu(action.menu(), name)
        return None


if __name__ == '__main__':
    # Launch Application
    app = QtGui.QApplication(sys.argv)
    anyApp = AnyApplication()
    anyApp.show()


    # Access Application with API
    print "\n## 1st ####################"
    apiMenu = MenuBar(anyApp.menuBar()).AddMenu("API")
    anMenu  = apiMenu.AddMenu("Analyse")

    print "\n## 2nd ####################"
    apiMenu = MenuBar(anyApp.menuBar()).AddMenu("API")
    exMenu  = apiMenu.AddMenu("Execute")

    sys.exit(app.exec_())

结果:

## 1st ####################

Search for:  API
Created:  API <PySide.QtGui.QMenu object at 0x00000000031E7488>

Search for:  Analyse
Created:  Analyse <PySide.QtGui.QMenu object at 0x00000000031E7408>

## 2nd ####################

Search for:  API
Found:  API [<PySide.QtGui.QAction object at 0x00000000031E7588>]

Search for:  Execute
Traceback (most recent call last):
  File "C:/test/qtMenu.py", line 92, in <module>
    exMenu  = apiMenu.AddMenu("Execute")
  File "C:/test/qtMenu.py", line 61, in AddMenu
    result = self.GetMenu(name)
  File "C:/test/qtMenu.py", line 71, in GetMenu
    for action in self.menu.actions():
RuntimeError: Internal C++ object (PySide.QtGui.QMenu) already deleted.

如何摆脱 PySide 的清理过程?还是我必须以不同的方式定义 QObject 才能让它们保持活力?

如果您将 PySide 导入更改为 from PyQt4 import QtGui,您会发现它可以与 PyQt 一起正常工作。

【问题讨论】:

    标签: python api pyqt pyside


    【解决方案1】:

    经过更多研究,我找到了答案here。 因此,如果对象创建是以“pythonic”方式完成的,那么 PySide 并不会过多地关注对象的父级。最好的办法是用父对象定义对象,然后将对象添加到它的父对象。

    def AddMenu(self, name):
        result = self.GetMenu(name)
        return result if result else \
            Menu( self.menuBar.addMenu( QtGui.QMenu(title=name, parent=self.menuBar) ).menu(), name)
    

    现在它按预期工作,并且对象不会被放入垃圾回收中进行清理。 QT cObject 现在正在处理它的关系,而不是 PySide 并保持对象处于活动状态。但是如果这个功能能在 PySide 的下一次更新中实现就好了,因为现在创建它的方式不是很“pythonic”

    【讨论】:

    • 仅供参考 PySide 这些天没有看到太多的发展。他们确实有一个错误跟踪器,因此您可以在那里发布问题。如果您想要更好的长期支持,我建议您迁移到 PyQt(尽管免费许可证对商业应用程序的限制稍大一些)
    • @three_pineapples:我必须使用booth,因为一些应用程序API 只支持PySide。我写了一些包装器库,它们会自动导入正确的系统来使用
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-21
    • 1970-01-01
    相关资源
    最近更新 更多