Is this PyQt 4 python bug or wrongly behaving code?
Asked Answered
R

2

11

Following code should create the QGraphicsView widget which owns one QGraphicsScene having text inside of it:

#!/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_())

This opens the window, puts the text there, but after I close window - python dumps core and several issues are printed out:

(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)

Versions: python2.7 2.7.3-0ubuntu3.1 python-qt4 4.9.1-2ubuntu1

Rhomb answered 15/9, 2012 at 0:14 Comment(0)
L
12

This is probably neither a PyQt bug, nor wrongly behaving code.

When python goes through its shutdown process, the order in which objects get deleted can be unpredictable. Occasionally, this may cause somewhat baffling error messages to appear.

Your script runs fine on my (non-Ubuntu) Linux machine - but when I close the window, I get this output:

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

Which, taken at face value, seems to make no sense at all...

However, it's usually pretty easy to get rid of such error messages by forcing the objects to be deleted in a different order.

One (slightly strange) way to do this is to just rename some of the objects. So for me, the error messages disappear if I simply change view to _view.

However, a perhaps better alternative is to make sure that certain key objects are connected together in a parent/child hierarchy:

    view = QGraphicsView()  
    scene = QGraphicsScene(view)

The reason for doing this, is that when deleteing an object, Qt will also automatically delete all of its descendant QObject nodes. This can help to ensure that the C++ side of PyQt objects is cleaned up before the python side (which is really at the core of what causes these kinds of problems).

Another possibility is to keep a global reference to the QApplication, and put everything else in a main function:

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())
Loux answered 17/9, 2012 at 16:14 Comment(2)
Making view the parent of scene is the best way to do it, IMO. ;-)Blowtorch
LOL well done, moving things into a separate main() method and returning exec_() got rid of my "segfault"Isomorph
S
13

It looks to be related to the QApplication object being deleted when quitting, but I'm not sure why. Your code worked fine for me under Windows but I got the same seg fault output as you under an Ubuntu install.

I managed to get a clean exit with the following code as a work around.

#!/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()
Stoffel answered 17/9, 2012 at 10:17 Comment(0)
L
12

This is probably neither a PyQt bug, nor wrongly behaving code.

When python goes through its shutdown process, the order in which objects get deleted can be unpredictable. Occasionally, this may cause somewhat baffling error messages to appear.

Your script runs fine on my (non-Ubuntu) Linux machine - but when I close the window, I get this output:

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

Which, taken at face value, seems to make no sense at all...

However, it's usually pretty easy to get rid of such error messages by forcing the objects to be deleted in a different order.

One (slightly strange) way to do this is to just rename some of the objects. So for me, the error messages disappear if I simply change view to _view.

However, a perhaps better alternative is to make sure that certain key objects are connected together in a parent/child hierarchy:

    view = QGraphicsView()  
    scene = QGraphicsScene(view)

The reason for doing this, is that when deleteing an object, Qt will also automatically delete all of its descendant QObject nodes. This can help to ensure that the C++ side of PyQt objects is cleaned up before the python side (which is really at the core of what causes these kinds of problems).

Another possibility is to keep a global reference to the QApplication, and put everything else in a main function:

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())
Loux answered 17/9, 2012 at 16:14 Comment(2)
Making view the parent of scene is the best way to do it, IMO. ;-)Blowtorch
LOL well done, moving things into a separate main() method and returning exec_() got rid of my "segfault"Isomorph

© 2022 - 2024 — McMap. All rights reserved.