PyQt 5:将QGraphicsScene渲染到QImage时,QPainter返回false

时间:2018-10-11 12:29:48

标签: python python-3.x pyqt5 qgraphicsscene qpainter

当前,我正在开发一个程序,以显示SIP-Trace日志文件。它是使用PyQt 5(.11.3)模块以python 3.7编写的,以加载和操作QDesigner中制作的GUI。它的主要功能是解析SIP-Trace文件,并将其作为序列图显示给具有QGraphicsObjects的QGraphicsScene。

我的问题出在以下方面:供以后参考,QGraphicsScene的内容应另存为图像文件,例如.jpg或.png。在Qt / PyQt文档中,我找到了有用的探测命令QGraphicsScene.render(),该命令使用QPainter将GraphicsScene的内容呈现为可保存文件,例如QImage。在过去的几天里,我尝试了几种在此处和其他地方找到的方法/示例代码,但是无法将GraphicsScene渲染到QImage到图像文件。由于我是Python和Qt的新手,因此我认为某些地方缺少一些基本设置。以下是我的代码的最低版本。

# -*- coding: utf8 -*-
"""Class for getting a sequence diagram of a sip traffic"""

from PyQt5.QtWidgets import *
from PyQt5 import uic
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys


class VoipGui(QMainWindow):
    """ Class that handles the interaction with the UI """
    def __init__(self, parent=None):
        super().__init__(parent)
        self.ui = uic.loadUi("main_window.ui", self)
        self.showMaximized()

        self.sequence_scene = QGraphicsScene()
        self.ui.graphicsView.setScene(self.sequence_scene)
        # self.sequence_scene.setSceneRect(0, 0, 990, 2048)

        # sets the spacing between nodes
        # For more than three nodes columns should be generated in a more automatic way
        self.left_column = 51
        self.middle_column = 381
        self.right_column = 711
        self.flow_height = 60  # Sets the spacing between the arrows in the flowchart

        # --------------------------------- /class init and var set -------------------------------------------

        self.actionOpenFile.triggered.connect(self.on_open_file)
        self.actionCloseFile.triggered.connect(self.on_close_file)
        self.actionCloseProgram.triggered.connect(self.close)
        self.actionSaveFile.triggered.connect(self.save_seq_image)

        # --------------------------------- /connecting slots and signals ----------------------------

    def on_open_file(self):
        """Dummy version of the open file dialog"""
        self.draw_node(self.left_column, 5, "192.168.2.1", 10)
        self.draw_node(self.middle_column, 5, "192.168.2.22", 10)

    def on_close_file(self):
        self.ui.textBrowser.clear()
        self.sequence_scene.clear()

    def save_seq_image(self):
        """ Here lies the problem: Save the rendered sequence scene to file for later use"""
        rect_f = self.sequence_scene.sceneRect()
        # rect = self.sequence_scene.sceneRect().toRect()
        # img = QPixmap(rect.size())

        img = QImage()
        p = QPainter()

        # p.setPen(QColor(255, 255, 255))
        # p.setViewport(rect)

        painting = p.begin(img)
        self.sequence_scene.render(p, target=QRectF(img.rect()), source=rect_f)
        p.end()

        if painting:
            print("Painter init pass")
        elif not painting:
            print("Painter init fail")

        saving = img.save("save.jpg")
        if saving:
            print("Saving Pass")
        elif not saving:
            print("Saving Not Pass")

    def draw_node(self, x_pos, y_pos, ip_address, y_stops):
        """Participating devices are displayed as these nodes"""
        width = 100.0
        height = 40.0
        pc_box = QGraphicsRectItem(x_pos - 50, y_pos, width, height)
        self.sequence_scene.addItem(pc_box)
        pc_ip = QGraphicsTextItem("%s" % ip_address)
        pc_ip.setPos(x_pos - 50, y_pos)
        self.sequence_scene.addItem(pc_ip)
        node_line = QGraphicsLineItem(x_pos, y_pos + 40, x_pos, y_pos + (y_stops * self.flow_height))
        self.sequence_scene.addItem(node_line)


def show_window():
    app = QApplication(sys.argv)
    dialog = VoipGui()
    dialog.show()
    sys.exit(app.exec_())


if __name__ == "__main__":
    show_window()

1 个答案:

答案 0 :(得分:0)

问题很简单,在render()中,您指示目标的大小等于QImage的大小,并且QImage的大小是多少?您如何使用QImage()大小为QSize(0, 0),因此无法生成图像,解决方案是创建一个大小为QImage

def save_seq_image(self):
    """ Here lies the problem: Save the rendered sequence scene to file for later use"""
    rect_f = self.sequence_scene.sceneRect()
    img = QImage(QSize(640, 480), QImage.Format_RGB888)
    img.fill(Qt.white)
    p = QPainter(img)
    self.sequence_scene.render(p, target=QRectF(img.rect()), source=rect_f)
    p.end()
    saving = img.save("save.jpg")
    print("Saving Pass" if saving else "Saving Not Pass")

输出:

enter image description here