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 运行效果
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)。