导入代码时删除了python QT底层对象

时间:2011-09-02 08:58:34

标签: python qt exec

我有一个简单的程序,它创建一个QGraphicsScene / View然后执行一个给定的文件(通过python的exec语句)和一些全局函数导出。

我的目标是只在新文件中定义场景代码,并且已经定义了一些辅助函数。

我的主程序中还有一个提供回调的线程,我想在回调的qgraphicsitems上做一些事情。

此处的示例定义了一个链接到一个回调的隐身动画:

from PySide import QtGui

# definition of an animation of invisibility
class AnimInvisible:
    def __init__(self, item):
        self.item = item

    def on_callback(self, tag):
        self.item.setVisible(tag.getProperty() != 0)

# creation of a simple QGraphicsRectItem
mon_rect = QtGui.QGraphicsRectItem(400, 300, 100, 50)
mon_rect.setBrush(QtGui.QBrush(QtGui.QColor('red')))

# this will add the rect to the scene defined in the file
# where the exec statement is done (exported by exec)
addItem(mon_rect)


a = AnimInvisible(mon_rect)
# this connect the a.on_callback on some changes from a thread. (exported from exec)
addCallback(a.on_callback, 'system:cmdamg')

这非常有效。但现在,如果我将AnimInvisible的代码放在另一个模块中 - 说动画 - 我在上面取代:

from animations import AnimInvisible

我收到错误,说内部C ++对象(PySide.QtGui.QGraphicsRectItem)已被删除..

这是一个我不理解的非常奇怪的行为。我也尝试使用PyQt而不是PySide,我得到了相同的行为(当AnimInvisible的代码在模块中时对象被删除,如果它在同一个文件中则没有问题。)

1 个答案:

答案 0 :(得分:1)

感谢你的评论alexisdm和varela,我发现了问题。

我做的是这样的事情:

class Synoptique:
    def __init__(self, w, h):
        self.view = QGraphicsView()
        self.scene = SynopScene()
        # some initialization ...

def openSynop(buApp, fname, w, h):
    synop = Synoptique(w, h)
    var_export = {
        'addItem': synop.addItem,
        'addCallback': buApp.addCallback,
    }
    exec open(fname) in var_export
    synop.view.show()

if __name__ == '__main__':
    app = QApplication(sys.argv)

    # buApp creation

    openSynop(buApp, 'synop.py', 800, 600)
    app.exec_()

但似乎对synop对象(包含QGraphicsView和Scene)的引用丢失了,因为它是openSynop函数中的局部变量。因此,引用QGraphicsView,场景和场景中的对象也会丢失。

处理它的一种方法是在函数外部,主调用中声明synop实例,或者从函数返回并保存synop引用。这解决了我的问题,例如:

def openSynop(buApp, fname, w, h):
    # same as before...

    return synop


if __name__ == '__main__':
    # same as before...

    s = openSynop(buApp, 'synop.py', 800, 600)
    app.exec_()

我现在明白我必须在QGraphicsView / scene上保留一个参考,以便稍后操作场景内的QGraphicsItem ......哇,这对我来说不太明显,再次感谢!