Это ошибка 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


person jhnsn    schedule 15.09.2012    source источник


Ответы (2)


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

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

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

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

Что, если принять за чистую монету, кажется, вообще не имеет смысла...

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

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

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

    view = QGraphicsView()  
    scene = QGraphicsScene(view)

Причина этого в том, что при удалении объекта Qt также автоматически удалит все его потомки QObject узлов. Это может помочь гарантировать, что сторона C++ объектов 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())
person ekhumoro    schedule 17.09.2012
comment
Сделать view родителем scene — лучший способ сделать это, ИМО. ;-) - person Peque; 13.07.2015
comment
LOL молодец, переместив вещи в отдельный метод main() и вернув exec_(), я избавился от моего segfault - person svenevs; 28.04.2017

Похоже, что это связано с удалением объекта 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()
person Gary Hughes    schedule 17.09.2012