Отображение изображения в QGraphicsScene - PullRequest
4 голосов
/ 07 января 2012

У меня есть короткий скрипт, который несколько раз изменяет изображение с помощью PIL. Я хотел бы иметь возможность отображать промежуточные этапы по мере их завершения, поэтому я добавил сцену QGraphics и пытаюсь отобразить этапы там. Он будет правильно определять размер и центрировать заключительный этап (последний, опубликованный перед выходом из функции), но отображает промежуточные этапы без изменения их размера или центровки.

Код для отправки изображения:

        #Code to generate the image and create the loop here...
        imgQ = ImageQt.ImageQt(img)
        pixMap = QtGui.QPixmap.fromImage(imgQ)

        scene = QtGui.QGraphicsScene()
        self.ui.previewGv.setScene(scene)
        pixMap = pixMap.scaled(self.ui.previewGv.size())
        #scene.clear()
        scene.addPixmap(pixMap)               
        self.ui.previewGv.repaint()
        self.ui.previewGv.show()

Есть ли способ заставить его правильно отображать каждый этап?

1 Ответ

8 голосов
/ 07 января 2012

Трудно определить вашу проблему без кода цикла и рабочего примера.Но у меня есть похожее тестовое приложение, надеюсь, оно поможет.

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import Image
import ImageQt
import ImageEnhance
import time

class TestWidget(QWidget):
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.scene = QGraphicsScene()
        self.view = QGraphicsView(self.scene)
        self.button = QPushButton("Do test")

        layout = QVBoxLayout()
        layout.addWidget(self.button)
        layout.addWidget(self.view)
        self.setLayout(layout)

        self.button.clicked.connect(self.do_test)

    def do_test(self):
        img = Image.open('image.png')
        enhancer = ImageEnhance.Brightness(img)
        for i in range(1, 8):
            img = enhancer.enhance(i)
            self.display_image(img)
            QCoreApplication.processEvents()  # let Qt do his work
            time.sleep(0.5)

    def display_image(self, img):
        self.scene.clear()
        w, h = img.size
        self.imgQ = ImageQt.ImageQt(img)  # we need to hold reference to imgQ, or it will crash
        pixMap = QPixmap.fromImage(self.imgQ)
        self.scene.addPixmap(pixMap)
        self.view.fitInView(QRectF(0, 0, w, h), Qt.KeepAspectRatio)
        self.scene.update()

if __name__ == "__main__":
    app = QApplication(sys.argv)
    widget = TestWidget()
    widget.resize(640, 480)
    widget.show()

    sys.exit(app.exec_())

Основные моменты:

  • Если вы выполняете некоторую обработку или sleep в цикле,вам нужно позвонить QCoreApplication.processEvents(), чтобы позволить Qt делать обновления.

  • Я сохраняю ссылку на ImageQt.ImageQt (self.imgQ), иначе она вылетит.

  • Как я понял, вы создаете QGraphicsScene в каждой итерации, лучшее решение создать его один раз, а затем вызвать scene.clear().

  • Масштабирование растрового изображения только для отображения его размера и центрирования стоит дорого, QGraphicsView.fitInView() сделано для этой цели.

...