Подтвердить что ты не робот

Является ли это ошибкой python PyQt 4 или неправильным ведением кода?

Следующий код должен создать виджет QGraphicsView, которому принадлежит один QGraphicsScene с текстом внутри него:

#!/usr/bin/python

import sys
from PyQt4.QtGui import *


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

  view = QGraphicsView()  
  scene = QGraphicsScene()

  scene.addText("Hello!")

  view.setScene(scene)
  view.show();

  sys.exit(app.exec_())

Это открывает окно, помещает туда текст, но после закрытия окна - выгружается ядро ​​python и выдается несколько проблем:

(python:5387): Gtk-CRITICAL **: IA__gtk_container_add: assertion `GTK_IS_CONTAINER (container)' failed

(python:5387): Gtk-CRITICAL **: IA__gtk_widget_realize: assertion `GTK_WIDGET_ANCHORED (widget) || GTK_IS_INVISIBLE (widget)' failed
...clip...
... above message is shown many, many times ...
...clip...
(python:5387): Gtk-CRITICAL **: IA__gtk_widget_realize: assertion `GTK_WIDGET_ANCHORED (widget) || GTK_IS_INVISIBLE (widget)' failed
Segmentation fault (core dumped)

Версия: python2.7 2.7.3-0ubuntu3.1 python-qt4 4.9.1-2ubuntu1

4b9b3361

Ответ 1

Это, вероятно, не ошибка PyQt, а неправильное поведение кода.

Когда python проходит процесс завершения, порядок, в котором объекты удаляются, может быть непредсказуемым. Иногда это может привести к появлению нескольких непонятных сообщений об ошибках.

Ваш script отлично работает на моей (не-Ubuntu) Linux-машине - но когда я закрываю окно, я получаю этот вывод:

$ python2 test.py 
QPixmap: Must construct a QApplication before a QPaintDevice
Aborted

Что, взятое по номиналу, кажется, не имеет никакого смысла...

Однако обычно легко избавиться от таких сообщений об ошибках, заставляя объекты удаляться в другом порядке.

Один (немного странный) способ сделать это - просто переименовать некоторые из объектов. Поэтому для меня сообщения об ошибках исчезают, если я просто изменяю view на _view.

Однако, возможно, лучшей альтернативой является убедиться, что определенные ключевые объекты соединены вместе в иерархии parent/child:

    view = QGraphicsView()  
    scene = QGraphicsScene(view)

Причиной этого является то, что при удалении объекта Qt автоматически удаляет все его потоки QObject. Это может помочь убедиться, что сторона С++ на PyQt очищена до стороны python (что действительно является причиной того, что вызывает эти проблемы).

Другая возможность - сохранить глобальную ссылку на QApplication и поместить все остальное в функцию main:

import sys
from PyQt4.QtGui import *

def main():
    view = QGraphicsView()
    scene = QGraphicsScene()
    scene.addText("Hello!")
    view.setScene(scene)
    view.show()
    return qApp.exec_()

if __name__ == '__main__':

    app = QApplication(sys.argv)
    sys.exit(main())

Ответ 2

Похоже, что это связано с удалением объекта QApplication при выходе, но я не уверен, почему. Ваш код работал отлично для меня под Windows, но я получил тот же самый вывод сбоя, что и при установке Ubuntu.

Мне удалось получить чистый выход со следующим кодом как работа.

#!/usr/bin/python

import sys
from PyQt4.QtGui import QApplication, QGraphicsView, QGraphicsScene


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

  view = QGraphicsView()  
  scene = QGraphicsScene()

  scene.addText("Hello!")

  view.setScene(scene)
  view.show()

  app.exec_()
  app.deleteLater()
  sys.exit()