Qt中使用QPdfWriter类结合QPainter类绘制并输出PDF文件
- 电脑硬件
- 2025-08-26 07:24:01

一.类的介绍 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文件由讯客互联电脑硬件栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“Qt中使用QPdfWriter类结合QPainter类绘制并输出PDF文件”