базовый объект Python QT удаляется при импорте кода - PullRequest
3 голосов
/ 02 сентября 2011

У меня есть простая программа, которая создает QGraphicsScene / View, а затем выполняет данный файл (с помощью оператора exec в python) с помощью некоторой функции глобальных экспортов.

Моя цель - определять код сцены только в новых файлах, некоторые функции помощников уже определены.

У меня также есть в моей основной программе поток, который доставляет обратные вызовы, и я хочу кое-что сделать с 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 Ответ

1 голос
/ 08 сентября 2011

Благодаря вашим комментариям 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, scene и объекты в сцене тоже потеряны.

Один из способов справиться с этим - объявить экземпляр 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, который находится внутри сцены ... Вау, это было не очевидно для меня, спасибо еще раз!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...