Qt中使用QPdfWriter类结合QPainter类绘制并输出PDF文件
一.类的介绍
1.QPdfWriter介绍
Qt中提供了一个直接可以处理PDF的类,这就是QPdfWriter类。
(1)PDF文件生成
支持创建新的PDF文件或覆盖已有文件,通过构造函数直接绑定文件路径或QFile对象;
默认生成矢量图形PDF,支持高分辨率输出(可设置DPI);
(2)页面属性配置
页面方向:通过setPageOrientation(QPageLayout::Orientation)设置纵向(Portrait)或横向(Landscape);
页面尺寸:使用setPageSize(QPageSize::A4)定义纸张大小,支持ISO标准尺寸(如A4、A3);
页边距:通过setPageMargins()调整内容区域与页边的距离;
(3)内容绘制
与QPainter深度集成,支持所有标准绘图操作:
图形:线段、矩形、椭圆、多边形等;
文本:多字体样式、对齐方式、旋转文字;
图像:支持PNG、JPG、SVG等格式的嵌入;
(4)多页面管理
通过QPainter::begin()和QPainter::end()控制绘制流程;
使用QPrinter::newPage()或手动分页逻辑实现多页文档;
2.QPainter介绍
(1)QPainter类功能
QPainter是Qt框架中用于2D图形绘制的核心类,提供高度优化的绘图功能,支持在QWidget、QImage、QPixmap、QPrinter等设备上进行绘制。其主要特性包括:
- 支持矢量图形(直线/曲线/几何图形)和位图操作;
- 提供坐标变换、复合模式、抗锯齿等高级特性;
- 集成字体渲染、图像合成等专业级功能;
- 必须通过paintEvent()事件或在继承自QPaintDevice的类中使用;
(2)QPainter类接口
- 基础绘图操作

- 文本与图像处理

- 状态控制与高级特性

QPainter类还有很多接口函数,尤其是跟绘制有关的,很多重载的接口方便不同情况的使用,具体可以参考官网的介绍QPainter类。
二.开发生成PDF文件
下面开始用上文中的两个类来封装一个专门用来绘制PDF文件的类。
1.使用前要注意:
- 坐标系系统:PDF坐标系原点在页面左上角,Y轴向下延伸,X轴向右延伸;
- 单位换算:使用QPageLayout::Millimeter设置毫米单位,绘制时默认使用像素单位;
- 图像缩放:推荐使用QRect参数控制图片显示尺寸,避免直接缩放;
- 字体嵌入:中文字体需通过QFontDatabase加载系统字体;
- 多页处理:通过QPdfWriter的newPage()创建新页面;
2.绘制流程梳理
- 想要操作PDF文件,首先得有个文件,使用QFile的对象指向文件,然后创建QPdfWriter类的对象,并将QPdfWriter绑定在该文件上,然后用QPdfWriter对象设定PDF的一些参数,比如DPI,绘制页面大小等。
- 其次,想要绘制得打开文件,调用QFile对象打开绑定的pdf格式的文件;
- 再次,创建QPainter类对象,用该对象的各个规制接口来绘制各种图形文字等,如果你要设计绘制的接口很多的话,这里其实是最耗时的;
- 最后,正确的释放资源,关闭文件;
3.代码说明
现在实操
- QtCreator上创建一个简单的应用程序项目,先编译下,确保原始项目没问题;
- 在程序界面上添加一个按钮,命名“btCreatePdf”,连接好按钮对应的点击信号槽;
- 添加新的C++类,继承自QObject,类命名“PdfGenerator”,这就是我们准备开发的一个专门操作PDF的自定义类,也就是我们所有对PDF的操作都在这个类里边完成;
- “PdfGenerator”类的设计开发,包含QPdfWriter,QPainter,QFont,QImage,QPageSize, QFile等类;创建QPdfWriter类的对象,QPainter类的对象,QFile类的对象;调用这些对象的接口实现PDF的绘制。
- 最后,在主程序中包含上面自定义类,在界面按钮“btCreatePdf”中调用其实现PDF绘制。
不多说,直接上代码:
PdfGenerator 类的头文件:
// pdfgenerator.h
#include <QObject>
#include <QPdfWriter>
#include <QPainter>
#include <QFont>
#include <QImage>
#include <QPageSize>
#include <QFile>class PdfGenerator : public QObject {Q_OBJECT
public:explicit PdfGenerator(const QString &fileName, QPagedPaintDevice::PageSize size = QPagedPaintDevice::PageSize::A4);~PdfGenerator();// 基础设置 void setMargins(qreal left, qreal top, qreal right, qreal bottom);void setResolution(int dpi);void newPage();bool beginPage();bool endPage();// 绘制接口//绘制线段void drawLine(const QPointF &start, const QPointF &end, const QColor &color, qreal width);//绘制文字void drawText(const QRectF &rect, const QString &text, const QFont &font, const QColor &color, Qt::Alignment align);//绘制图片void drawImage(const QRectF &rect, const QString &imagePath, bool keepAspectRatio);//绘制矩形void drawRect(const QRectF &rect, const QColor &fillColor, const QColor &borderColor, qreal borderWidth);//绘制椭圆void drawEllipse(const QRectF &rect, const QColor &fillColor, const QColor &borderColor, qreal borderWidth);//想设计其他绘制接口继续往下加 private:QPdfWriter *m_writer = nullptr;QPainter *m_painter = nullptr;QRect m_pageRect;QFile m_pdfFile;
};
PdfGenerator 类的cpp文件
#include "PdfGenerator.h"
#include <QtDebug>
// pdfgenerator.cpp
PdfGenerator::PdfGenerator(const QString &fileName, QPagedPaintDevice::PageSize size)
{m_pdfFile.setFileName(fileName);m_writer = new QPdfWriter(&m_pdfFile);m_writer->setPageSize(size);m_writer->setResolution(300);m_writer->setPageMargins(QMarginsF(20, 20, 20, 20), QPageLayout::Millimeter);m_pageRect = m_writer->pageLayout().paintRectPixels(m_writer->resolution());// 计算可绘制区域 m_pageRect = QRect(0, 0, m_writer->width(), m_writer->height());if(!m_pdfFile.open(QIODevice::WriteOnly))return ;}PdfGenerator::~PdfGenerator()
{if (m_painter->isActive()){m_painter->end();}delete m_painter;delete m_writer;
}void PdfGenerator::setMargins(qreal left, qreal top, qreal right, qreal bottom)
{m_writer->setPageMargins(QMarginsF(left, top, right, bottom), QPageLayout::Millimeter);m_pageRect = m_writer->pageLayout().paintRectPixels(m_writer->resolution()); // 更新绘制区域[5]()
}void PdfGenerator::newPage()
{// 创建新页m_writer->newPage();
}bool PdfGenerator::beginPage(){bool bRet = false;if(nullptr == m_painter){m_painter = new QPainter(m_writer);}//启用抗锯齿m_painter->setRenderHint(QPainter::Antialiasing);if (nullptr != m_painter){m_painter->begin(m_writer);//m_painter->reset(new QPainter(m_writer.data()));bRet = m_painter->isActive();}qDebug() << "beginPage bRet is " << bRet;return bRet;
}bool PdfGenerator::endPage() {if (m_painter && m_painter->isActive()){m_painter->end();m_writer->deleteLater();m_pdfFile.close();return true;}m_pdfFile.close();return false;
}// 绘制线段
void PdfGenerator::drawLine(const QPointF &start, const QPointF &end, const QColor &color, qreal width)
{if (!m_painter->isActive())return;m_painter->save();m_painter->setPen(QPen(color, width));m_painter->drawLine(start, end);m_painter->restore();
}// 绘制文本(支持对齐)
void PdfGenerator::drawText(const QRectF &rect, const QString &text, const QFont &font, const QColor &color, Qt::Alignment align)
{if (!m_painter->isActive()) return;m_painter->save();m_painter->setFont(font);m_painter->setPen(color);m_painter->drawText(rect, static_cast<int>(align), text);m_painter->restore();
}// 绘制图片(自动缩放)
void PdfGenerator::drawImage(const QRectF &rect, const QString &imagePath, bool keepAspectRatio)
{if (!m_painter->isActive())return;QPixmap pixmap(imagePath);if (pixmap.isNull()) return;QRectF targetRect = rect;if (keepAspectRatio) {QSizeF scaled = pixmap.size().scaled(rect.size().toSize(), Qt::KeepAspectRatio);targetRect.setSize(scaled); }m_painter->drawPixmap(targetRect, pixmap, pixmap.rect());
}// 绘制矩形(支持填充)
void PdfGenerator::drawRect(const QRectF &rect, const QColor &fillColor, const QColor &borderColor, qreal borderWidth)
{if (!m_painter->isActive())return;m_painter->save();m_painter->setBrush(QBrush(fillColor));m_painter->setPen(QPen(borderColor, borderWidth));m_painter->drawRect(rect);m_painter->restore();
}// 绘制椭圆
void PdfGenerator::drawEllipse(const QRectF &rect, const QColor &fillColor, const QColor &borderColor, qreal borderWidth)
{if (!m_painter->isActive()) return;m_painter->save();m_painter->setBrush(QBrush(fillColor));m_painter->setPen(QPen(borderColor, borderWidth));m_painter->drawEllipse(rect);m_painter->restore();
}
主程序按钮调用PdfGenerator类绘制PDF
//创建Pdf
void MainWindow::on_btCreatePdf_clicked()
{qDebug() << "into on_btCreatePdf_clicked";PdfGenerator doc("E:/test/output.pdf");if (doc.beginPage()){qDebug() << "beginPage success";// 绘制灰色线段doc.drawLine(QPointF(20, 60), QPointF(150, 200), Qt::lightGray, 2.0);// 添加图片(保持比例),例子的资源里没有添加这张图片,所以下面PDF里没有绘制出来图片doc.drawImage(QRectF(100, 100, 100, 100), "logo.png", false);// 绘制蓝色文字QFont font("Arial", 12, QFont::Bold);doc.drawText(QRectF(70, 270, 270, 50), "Hello PDF!", font, Qt::blue, Qt::AlignVCenter | Qt::AlignHCenter);// 绘制绿色填充矩形doc.drawRect(QRectF(300, 150, 100, 40), Qt::green, Qt::black, 1.5);// 绘制黄色边框椭圆doc.drawEllipse(QRectF(250, 200, 100, 80), Qt::transparent, Qt::yellow, 2.0);doc.endPage();}}
执行后,展示结果:

以此自定义PdfGenerator类作为基础,后续可以根据QPainter类本身带有的各种图形绘制功能,封装你想做的绘制接口,实际项目应用中,就以你封装的接口进行各种布局绘制操作,来完成项目要求。
相关文章:
Qt中使用QPdfWriter类结合QPainter类绘制并输出PDF文件
一.类的介绍 1.QPdfWriter介绍 Qt中提供了一个直接可以处理PDF的类,这就是QPdfWriter类。 (1)PDF文件生成 支持创建新的PDF文件或覆盖已有文件,通过构造函数直接绑定文件路径或QFile对象; 默认生成矢量图形PDF&#…...
Android开发-深入解析Android中的AIDL及其应用场景
深入解析 Android 中的 AIDL 及其应用场景 1. 前言2. AIDL 的核心概念3. AIDL 的实现步骤3.1. 定义 AIDL 接口文件3.2. 实现服务端(Service)3.3. 客户端绑定与调用 4. AIDL 的典型应用场景4.1. 多进程应用4.2. 与系统服务交互4.3. 高性能 IPC4.4. 跨应用…...
RT-Thread+STM32L475VET6实现红外遥控实验
文章目录 前言一、板载资源介绍二、具体步骤1. 确定红外接收头引脚编号2. 下载infrared软件包3. 配置infrared软件包4. 打开STM32CubeMX进行相关配置4.1 使用外部高速时钟,并修改时钟树4.2 打开定时器16(定时器根据自己需求调整)4.3 打开串口4.4 生成工程 5. 打开HW…...
【机器学习】衡量线性回归算法最好的指标:R Squared
衡量线性回归算法最好的指标:R Squared 一、摘要二、回归算法评价指标与R Squared指标介绍三、R Squared的编程实践 一、摘要 本文主要介绍了线性回归算法中用于衡量模型优劣的重要指标——R Squared(R方)。R方用于比较模型预测结果与实际结…...
设计模式-Java
一、创建型模式 1. 单例模式 定义 确保一个类只有一个实例,并提供一个全局访问点。 实现方式 饿汉式(线程安全,但可能浪费资源) public class Singleton {// 静态变量,类加载时初始化private static final Singlet…...
代码讲解系列-CV(五)——语义分割基础
文章目录 一、图像分割标注1.1 Labelme标注1.2 SAM辅助1.3 json格式 二、数据解析2.1 Dataset2.2 train.py2.2.1 取参2.2.2 分割和数据集的读取 三、Unet网络搭建3.1 Unet3.2 Network 四、损失函数和指标4.1 DICE系数4.2 损失函数4.3 半精度训练 五、SAM六、作业 语义分割是图片…...
在mfc中使用自定义三维向量类和计算多个三维向量的平均值
先添加一个普通类, Vector3.h, // Vector3.h: interface for the Vector3 class. // //#if !defined(AFX_VECTOR3_H__53D34D26_95FF_4377_BD54_57F4271918A4__INCLUDED_) #define AFX_VECTOR3_H__53D34D26_95FF_4377_BD54_57F4271918A4__INCLUDED_#if _MSC_VER > 1000 #p…...
RDMA ibverbs_API功能说明
设备管理 获取当前活动网卡 返回当前rdma设备列表 struct ibv_device **ibv_get_device_list(int *num_devices);//使用 struct ibv_device **dev_list ibv_get_device_list(NULL);获取网卡名 返回网卡名字字符串:如"mlx5_0",一般通过网卡…...
【C++语言】string 类
一、为什么要学习 string 类 C语言中,字符串是以 “\0” 结尾的一些字符的集合,为了操作方便,C标准库中提供了一些 str 系列的库函数,但是这些库函数与字符串是分离开的,不太符合 OOP 的思想,而且底层空间需…...
快速上手gdb/cgdb
Linux调试器-gdb使用 1.背景2.调试原理、技巧命令2.1指令2.2 本质2.3 技巧 1.背景 程序的发布方式有两种,debug模式和release模式 Linux gcc/g出来的二进制程序,默认是release模式 要使用gdb调试,必须在源代码生成二进制程序的时候, 加上 -g…...
《养生》(二)
一、基础生活调整 1.作息规律 固定每天7-8小时睡眠,尽量22:30前入睡,晨起后拉开窗帘晒太阳5分钟,调节生物钟 2.饮食优化 三餐定时,每餐细嚼慢咽20次以上,优先吃蔬菜和蛋白质(如鸡蛋、豆腐&#x…...
JAVA:集成 Drools 业务规则引擎的技术指南
1、简述 Drools 是一个强大的业务规则引擎,适用于需要动态决策或规则管理的场景。它允许开发人员将业务逻辑与应用代码分离,使得业务人员可以通过规则文件维护和更新规则,而无需修改应用代码。本文将介绍 Drools 的基本概念、配置方式&#…...
GeoHD - 一种用于智慧城市热点探测的Python工具箱
GeoHD - 一种用于智慧城市热点探测的Python工具箱 详细原理请参考:Yan, Y., Quan, W., Wang, H., 2024. A data‐driven adaptive geospatial hotspot detection approach in smart cities. Trans. GIS tgis.13137. 代码下载:下载 1. 简介 在城市数据…...
记一次Ngnix配置
记一次Ngnix配置 配置Ngnix配置防火墙 假设一个服务器中有一个公网IP、一个内网IP,另外已经部署好后台服务的接口地址为http://内网ip:8088。 配置Ngnix 找到Ngnix的配置文件,通过在Ngnix的安装路径下的 \conf\nginx.conf 文件。 worker_processes 1;…...
2024年国赛高教杯数学建模C题农作物的种植策略解题全过程文档及程序
2024年国赛高教杯数学建模 C题 农作物的种植策略 原题再现 根据乡村的实际情况,充分利用有限的耕地资源,因地制宜,发展有机种植产业,对乡村经济的可持续发展具有重要的现实意义。选择适宜的农作物,优化种植策略&…...
java基础语知识(8)
类之间的关系 在类之间,最常见的关系有: 依赖(“uses-a”);聚合(“has-a”);继承(“is-a”)。 依赖:一种使用关系,即一个类的实现需要另一个类的协助&#x…...
室内定位精度方案对比
室内定位精度方案对比:成本、开发难度与精度的权衡 索引 引言 Wi-Fi 定位方案 定位原理 成本分析 开发难度 定位精度 蓝牙定位方案 定位原理 成本分析 开发难度 定位精度 超宽带(UWB)定位方案 定位原理 成本分析 开发难度 定…...
Pytorch深度学习教程_5_编写第一个神经网络
欢迎来到《pytorch深度学习教程》系列的第五篇!在前面的四篇中,我们已经介绍了Python、numpy及pytorch的基本使用,并在上一个教程中介绍了梯度。今天,我们将探索神经网络,对于神经网络进行概述并进行简单的实践学习 欢…...
ImportError: cannot import name ‘FixtureDef‘ from ‘pytest‘
错误信息表明 pytest 在尝试导入 FixtureDef 时出现了问题。通常是由于 pytest 版本不兼容 或 插件版本冲突 引起的。以下是详细的排查步骤和解决方案: 1. 检查 pytest 版本 首先,确认当前安装的 pytest 版本。某些插件可能需要特定版本的 pytest 才能…...
改BUG:Mock测试的时候,when失效
问题再现: 这里我写了一测试用户注册接口的测试类,并通过when模拟下层的服务,但实际上when并没有奏效,还是走了真实的service层的逻辑。 package cn.ac.evo.review.test;import cn.ac.evo.review.user.UserMainApplication; imp…...
2026最新华为OD新系统机试解析 + 最新题库 + 备考策略
华为OD在2026年4月1号迎来了新系统升级,华为OD新系统机试相比之前的机考模式,产生了几个重大变化。下面重点给小伙伴说明一下华为OD新系统机考重大变化以及在华为OD机试新机考模式下如何快速备考。 华为OD机试新系统变化介绍 机试时间固定 华为OD新系…...
MCP 2026跨服务器编排落地手册(2024Q4唯一兼容RFC-9321的工业级方案)
更多请点击: https://intelliparadigm.com 第一章:MCP 2026跨服务器编排的核心演进与RFC-9321对齐原理 MCP 2026(Multi-Cluster Protocol 2026)标志着分布式系统控制平面从单集群协调迈向全域协同的关键跃迁。其核心演进聚焦于状…...
Rust 所有权系统:借用检查器与生命周期
# Rust异步编程:Tokio运行时深度解析> **版本说明**:本文基于 Tokio 1.x 版本和 Rust 1.75 编写,所有代码示例均经过测试验证。## 📚 引言异步编程是现代高性能服务的基石,而 Tokio 作为 Rust 生态中最成熟的异步运…...
微软Azure AKS部署Magma云原生5G核心网实战指南
1. 项目概述:从“熔岩”到云原生电信核心网 如果你在电信行业或者云原生技术圈里待过一阵子,大概率听说过“Magma”这个名字。这可不是什么火山喷发的岩浆,而是一个由Meta(原Facebook)发起,并已捐赠给Linu…...
如何用Fan Control彻底解决Windows电脑风扇噪音问题:终极免费控制指南
如何用Fan Control彻底解决Windows电脑风扇噪音问题:终极免费控制指南 【免费下载链接】FanControl.Releases This is the release repository for Fan Control, a highly customizable fan controlling software for Windows. 项目地址: https://gitcode.com/Git…...
终极iOS 15-16 iCloud绕过教程:applera1n工具完整使用指南
终极iOS 15-16 iCloud绕过教程:applera1n工具完整使用指南 【免费下载链接】applera1n icloud bypass for ios 15-16 项目地址: https://gitcode.com/gh_mirrors/ap/applera1n 你是否遇到过iPhone或iPad因iCloud激活锁而无法使用的困境?当你恢复出…...
Boot Camp驱动自动化革命:Brigadier如何将45分钟部署压缩至5分钟
Boot Camp驱动自动化革命:Brigadier如何将45分钟部署压缩至5分钟 【免费下载链接】brigadier Fetch and install Boot Camp ESDs with ease. 项目地址: https://gitcode.com/gh_mirrors/bri/brigadier 在企业混合计算环境中,Mac设备Boot Camp驱动…...
EB Garamond 12:当文艺复兴字体遇见现代学术引用系统 [特殊字符]
EB Garamond 12:当文艺复兴字体遇见现代学术引用系统 🎨 【免费下载链接】EBGaramond12 项目地址: https://gitcode.com/gh_mirrors/eb/EBGaramond12 你是否曾为寻找一款既具备古典美学又支持现代学术需求的字体而苦恼?🤔…...
番茄小说下载器:三界面一体化的Rust数字阅读解决方案
番茄小说下载器:三界面一体化的Rust数字阅读解决方案 【免费下载链接】Tomato-Novel-Downloader 番茄小说下载器不精简版 项目地址: https://gitcode.com/gh_mirrors/to/Tomato-Novel-Downloader 在现代数字阅读生态中,读者常面临内容获取分散、格…...
终极指南:5个简单步骤在电脑上免费畅玩Switch游戏
终极指南:5个简单步骤在电脑上免费畅玩Switch游戏 【免费下载链接】Ryujinx 用 C# 编写的实验性 Nintendo Switch 模拟器 项目地址: https://gitcode.com/GitHub_Trending/ry/Ryujinx 你是否梦想着在电脑上体验任天堂Switch的精彩游戏世界?Ryujin…...
