【问题标题】:Is this PyQt 4 python bug or wrongly behaving code?这是 PyQt 4 python 错误还是行为错误的代码?
【发布时间】:2012-09-08 03:33:32
【问题描述】:

以下代码应创建 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

【问题讨论】:

    标签: python-2.7 segmentation-fault pyqt pyqt4 qgraphicsscene


    【解决方案1】:

    它看起来与退出时被删除的 QApplication 对象有关,但我不确定为什么。您的代码在 Windows 下对我来说运行良好,但在 Ubuntu 安装下我得到了与您相同的 seg 错误输出。

    我设法通过以下代码获得了一个干净的退出。

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

    【讨论】:

      【解决方案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 节点。这有助于确保在 python 端之前清理 PyQt 对象的 C++ 端(这确实是导致这类问题的核心)。

      另一种可能性是保持对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())
      

      【讨论】:

      • view 成为scene 的父级是最好的方法,IMO。 ;-)
      • LOL 干得好,将事情转移到单独的 main() 方法中并返回 exec_() 摆脱了我的“segfault”
      猜你喜欢
      • 2011-05-21
      • 1970-01-01
      • 1970-01-01
      • 2011-07-08
      • 1970-01-01
      • 2017-09-28
      • 2012-01-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多