2012-09-15 33 views
11

mã sau nên tạo widget QGraphicsView công ty sở hữu một QGraphicsScene có văn bản bên trong của nó:Đây có phải là lỗi python PyQt 4 hoặc mã hoạt động sai không?

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

này mở ra cửa sổ, đặt các văn bản đó, nhưng sau khi tôi đóng cửa sổ - python bãi lõi và một số vấn đề được in ra:

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

phiên bản: python2.7 2.7.3-0ubuntu3.1 python-qt4 4.9.1-2ubuntu1

Trả lời

10

Đây có thể không phải là lỗi PyQt và mã hoạt động sai.

Khi python đi qua quá trình tắt máy, thứ tự các đối tượng bị xóa có thể không thể đoán trước được. Đôi khi, điều này có thể khiến một số thông báo lỗi có thể xuất hiện.

Kịch bản của bạn chạy tốt trên máy Linux (Ubuntu không) của tôi - nhưng khi tôi đóng cửa sổ, tôi nhận được kết quả này:

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

Trong đó, thực hiện tại mệnh giá, dường như không có ý nghĩa ở tất cả ...

Tuy nhiên, thường khá dễ dàng để loại bỏ các thông báo lỗi đó bằng cách buộc các đối tượng bị xóa theo một thứ tự khác.

Một cách (hơi lạ) để thực hiện việc này là chỉ đổi tên một số đối tượng. Vì vậy, đối với tôi, các thông báo lỗi biến mất nếu tôi chỉ cần thay đổi view thành _view.

Tuy nhiên, một sự thay thế có lẽ tốt hơn là để đảm bảo rằng một số đối tượng chính được kết nối với nhau trong một hệ thống cấp bậc phụ huynh/trẻ em:

view = QGraphicsView() 
    scene = QGraphicsScene(view) 

Lý do để làm điều này, là khi deleteing một đối tượng, Qt sẽ cũng tự động xóa tất cả các nút hậu duệ của nó QObject. Điều này có thể giúp đảm bảo rằng bên C++ của các đối tượng PyQt được làm sạch trước mặt python (vốn thực sự là cốt lõi của nguyên nhân gây ra những vấn đề này).

Một khả năng khác là để giữ một tham chiếu toàn cầu vào QApplication, và đặt mọi thứ khác trong một hàm 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()) 
+0

Đặt 'view' là cha mẹ của' scene' là cách tốt nhất để làm điều đó, IMO. ;-) – Peque

+0

LOL cũng được thực hiện, di chuyển mọi thứ vào một phương thức 'main()' riêng biệt và trả về 'exec _()' đã loại bỏ "segfault" của tôi – sjm324

13

Có vẻ t o có liên quan đến đối tượng QApplication bị xóa khi bỏ, nhưng tôi không chắc tại sao. Mã của bạn làm việc tốt cho tôi trong Windows nhưng tôi có cùng một đầu ra lỗi seg khi bạn đang cài đặt Ubuntu.

Tôi đã quản lý để có được một lối ra sạch với mã sau đây như một công việc xung quanh.

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

Thêm 'app.deleteLater() 'đã làm các trick. Cảm ơn! – Onlyjus