【PyQt】QGraphicsView场景导出为图片

1 需求

需要将用户绘制的场景导出为图片。即

QGraphicsView中的Scene导出为图片。

2 代码

# 提示:此函数应能访问 QGraphicsView 对象。
# 参考:作者的项目中,此函数在某个QMainWindow类中,作为导出按钮的槽函数。

import sys
import PyQt5.QtGui

def slotExpMap(self):
    """将图形导出为图片保存"""
    # 注意view设置的sceneRect会遮盖scene设置的sceneRect
    # 此处要根据你的代码修改,也可能是:
    # sceneWidth = self.view.scene().sceneRect().width()
    sceneWidth = self.view.sceneRect().width()  # 场景宽度
    sceneHeight = self.view.sceneRect().height()

    # 空白图片
    img = QImage(int(sceneWidth), int(sceneHeight), PyQt5.QtGui.QImage.Format.Format_RGB32)

    # 将空白图片作为painter的painter device,即绘图设备
    painter = QPainter()
    painter.begin(img)  # 开始绘制

    # 图片等待绘制的区域
    targetRect = QRectF(0, 0, sceneWidth, sceneHeight)

    # 场景被临摹(拍照)的区域
    sourceRect = QRectF(-sceneWidth/2, -sceneHeight/2, sceneWidth, sceneHeight)

    # 开始渲染绘制
    self.view.scene().render(painter, targetRect, sourceRect)

    # 必须手动关闭绘制painter,原Qt(C++)由析构函数自动调用,但在Python中需手动调用
    painter.end()

    # 用户选择保存位置的对话框,返回:文件路径,文件类型
    destpath, filetype = QFileDialog.getSaveFileName(self, "文件保存", "hello.png", "图片 (*.png)")

    imgWriter = QImageWriter(destpath)  # 使用imgWriter更加安全,可显示错误提示
    if destpath:  # 如果获取的路径非空
        if imgWriter.write(img):
            QMessageBox.information(self, "提示", "导出成功")
        else:
            QMessageBox.information(self, "错误", imgWriter.errorString())
    else:
        QMessageBox.information(self, "提示", "未选择保存位置,文件保存操作已取消")

3 运行效果

【PyQt】QGraphicsView场景导出为图片_第1张图片

4 特别说明

因对painter类不熟悉,在调试时,总是出现图片正常保存后,程序报

进程已结束,退出代码-1073740791(0xC0000409)

 的错误。仅有错误代码,无任何提示文字,完全无从下手。后按照 此文 对PyCharm进行设置之后,才出现错误提示。

QPaintDevice: Cannot destroy paint device that is being painted

绘图设备:不能销毁还在绘制的设备。

很明显,painter没有正常的结束绘制过程。 

作为局部变量先声明先入栈的 img 在函数结束时,先出栈被销毁,但是此时 painter 还没有释放 img(painter device),于是互相产生矛盾,painter 生气了,导致程序闪退!

然后,我认真的把 painter的 begin() 和 end() 都写上去。程序莫名其妙退出的问题也解决了。

5 总结

使用Painter时,最安全的做法是使用 beging() 和 end() 方法。

# 最安全的方法
painter = QPainter()
painter.beging(img)
# 绘制图形时, 等待绘制的设备img 始终被painter占用
painter.end()
# 有始有终

而不是简单的使用 painter = QPainter(img)。

你可能感兴趣的:(PyQt,Qt,pyqt)