QT 使用QPdfWriter和QPainter绘制PDF文件

news2025/5/18 3:03:30

QT如何生产pdf文件,网上有许多文章介绍,我也是看了网上的文章,看他们的代码,自己琢磨琢磨,才有了本编博客;

其他什么就不详细说了,本篇博客介绍的QPdfWriter和QPainter绘制PDF文件;对pdf这里是绘制出来的,没有什么规范的格式,都是通过xy坐标绘制出来的。

QPdfWriter类设置pdf的基础设置;QPainter类绘制文本,图片矩形等;

以下代码参考博客:Qt中使用QPdfWriter类结合QPainter类绘制并输出PDF文件-CSDN博客

自己稍微做了调整了修改!

反正得自己会QPainter绘制,否则你无法绘制pdf文件出来!!!

头文件:

#include <QPdfWriter>
#include <QDesktopServices>
#include <QtPrintSupport/QPrinter>
#include <QtPrintSupport/QtPrintSupport>

一、步骤

绘制pdf有以下步骤:

1.选择需要导出的pdf文件路径;

2.创建pdf文件;

3.创建生成pdf类,作为绘图设备;

4.绘制PDF;

5.查看绘制好的pdf。

void Widget::exportPdf()
{
    //一、选择保存pdf文件路径
    QString sPath = QFileDialog::getSaveFileName(this, tr("另存为"), "/", tr("Text Files (*.pdf)"));
    if(sPath.isEmpty())
    {
        return;
    }
    qDebug() << sPath;

    //二、创建pdf文件
    QFile pdfFile(sPath);
    pdfFile.open(QIODevice::WriteOnly);

    //三、创建生成pdf类,作为绘图设备
    QPdfWriter *pPdfWriter = new QPdfWriter(&pdfFile);
    pPdfWriter->setResolution(300);      // 将打印设备的分辨率设置为屏幕分辨率
    pPdfWriter->setPageSize(QPagedPaintDevice::A4);             // 设置纸张为A4纸
    pPdfWriter->setPageMargins(QMarginsF(30, 30, 30, 30));      // 设置页边距 顺序是:左上右下

    //四、开始绘制PDF
    //paintPdf(pPdfWriter);

    delete pPdfWriter;
    pdfFile.close();

    //通过其它PDF阅读器来打开刚刚绘制的PDF
    QDesktopServices::openUrl(QUrl::fromLocalFile(sPath));
}

二、效果展示

三、代码实现

#include "widget.h"
#include "ui_widget.h"

#include <QFileDialog>
#include <QStandardPaths>
#include <QPdfWriter>
#include <QDebug>
#include <QDesktopServices>
#include <QMessageBox>
#include <QtPrintSupport/QPrinter>
#include <QtPrintSupport/QtPrintSupport>

#include <pdfgenerator.h>

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    createPDF();
}

Widget::~Widget()
{
    delete ui;
}

void Widget::createPDF()
{
    int y = 0;
    QString path = "/home/UOS/Desktop/3.pdf";

    PdfGenerator *pdfGenerator = new PdfGenerator;
    bool flag = pdfGenerator->setFileName(path);
    if (!flag) {
        return ;
    }

    int nPdfWidth = pdfGenerator->getPdfWidth();

    pdfGenerator->beginPage();

    QPixmap p;
    p.load(":/007.jpg");
    int pHeight = pdfGenerator->drawImage(QRectF(0, y, 150, 150), p);

    y += pHeight + 50;


    // 绘制表格
    y += 100;
    QFont f = QFont("宋体", 18, 36);
    QColor blackColor = QColor(0,0,0);

    pdfGenerator->drawRect(QRectF(0, y, nPdfWidth, 200), blackColor, 2, QColor(100, 0, 200, 50));
    pdfGenerator->drawText(QRectF(0, y, nPdfWidth, 200), "这是标题文本!", QFont("宋体", 32, 64));


    // 绘制科目
    y += 200;

    int nClassWidthFlag = nPdfWidth / (8);
    int nClassWidth = nClassWidthFlag;

    QList<QString> classList;
    classList << "语文" << "数学" << "英语" << "历史" << "政治" << "地理" << "音乐" << "体育";
    int classx = 0;
    for (int i = 0; i < classList.count(); i++) {
        pdfGenerator->drawRect(QRectF(classx, y, nClassWidth, 100), blackColor, 2);
        pdfGenerator->drawText(QRectF(classx, y, nClassWidth, 100), classList.at(i), QFont("宋体", 12, 20), QColor(200, 100, 100), Qt::AlignCenter);

        classx += nClassWidth;
        if (7 == i + 1) {
            int n = nPdfWidth - (classx + nClassWidth);
            nClassWidth += n;
        }
    }



    // 绘制个人信息
    y += 100;

    int nPersonDescriptionWidth = nClassWidthFlag * 2;

    QList<QList<QString>> descriptionList;
    QList<QString> list;
    list << "小米" << "男" << "15";
    descriptionList << list;
    list.clear();
    list << "小明" << "男" << "20";
    descriptionList << list;
    list.clear();
    list << "小红" << "女" << "21";
    descriptionList << list;
    list.clear();
    list << "姓名" << "性别" << "年龄";


    int nPersonDescriptionHeight = 120 + descriptionList.count() * 100;

    pdfGenerator->drawRect(QRect(0, y, nPersonDescriptionWidth, nPersonDescriptionHeight));
    pdfGenerator->drawText(QRect(0, y, nPersonDescriptionWidth, nPersonDescriptionHeight), "个人信息",
                           QFont("宋体", 20, 40), QColor(100, 100, 255));



    int nMessageX = nPersonDescriptionWidth;
    int nMessageWidth = nPersonDescriptionWidth;
    for (int i = 0; i < list.count(); i++) {
        pdfGenerator->drawRect(QRect(nMessageX, y, nMessageWidth, 120));
        pdfGenerator->drawText(QRect(nMessageX, y, nMessageWidth, 120), list.at(i), QFont("宋体", 18, 30), QColor(200, 50, 50));

        nMessageX += nPersonDescriptionWidth;
        if (list.count()-1 == i + 1) {
            int n = nPdfWidth - (nMessageX + nPersonDescriptionWidth);
            nMessageWidth += n;
        }
    }


    y += 120;

    int nPersonX = nPersonDescriptionWidth;
    int nPersonWidth = nPersonDescriptionWidth;
    for (int i = 0; i < descriptionList.count(); ++i) {
        QList<QString> list = descriptionList.at(i);

        for (int j = 0; j < list.count(); ++j) {
            pdfGenerator->drawRect(QRect(nPersonX, y, nPersonWidth, 100));
            pdfGenerator->drawText(QRect(nPersonX, y, nPersonWidth, 100), list.at(j), pdfGenerator->getBaseFont());

            nPersonX += nPersonDescriptionWidth;
            if (list.count()-1 == j + 1) {
                int n = nPdfWidth - (nPersonX + nPersonDescriptionWidth);
                nPersonWidth += n;
            }
        }

        y += 100;

        nPersonX = nPersonDescriptionWidth;
        nPersonWidth = nPersonDescriptionWidth;
    }




    // 绘制详细信息
    descriptionList.clear();
    list.clear();
    list << "小明" << "swim" << "擅长蛙泳" << "170cm";
    descriptionList << list;
    list.clear();
    list << "小红" << "dance" << "街舞鼻祖" << "160cm";
    descriptionList << list;
    list.clear();
    list << "小黄" << "run" << "短跑小王子" << "166cm";
    descriptionList << list;
    list.clear();
    list << "小绿" << "jump" << "跳高运动员" << "196cm";
    descriptionList << list;
    list.clear();
    list << "姓名" << "爱好" << "特点" << "身高";


    int nDetailedInformationWidth = nClassWidthFlag * 2;
    int nDetailedInformationHeight = 120 + descriptionList.count() * 100;

    pdfGenerator->drawRect(QRect(0, y, nDetailedInformationWidth, nDetailedInformationHeight));
    pdfGenerator->drawText(QRect(0, y, nDetailedInformationWidth, nDetailedInformationHeight), "详细信息",
                           QFont("宋体", 20, 40), QColor(100, 100, 255));



    int nInformationTotalWidth = nPdfWidth - nDetailedInformationWidth;
    int nInformationOneWidth = nInformationTotalWidth / descriptionList.count();

    int nDetailedX = nDetailedInformationWidth;
    int nDetailedWidth = nInformationOneWidth;
    for (int i = 0; i < list.count(); i++) {
        pdfGenerator->drawRect(QRect(nDetailedX, y, nDetailedWidth, 120));
        pdfGenerator->drawText(QRect(nDetailedX, y, nDetailedWidth, 120), list.at(i), QFont("宋体", 20, 30));

        nDetailedX += nDetailedWidth;
        if (list.count()-1 == i + 1) {
            int n = nPdfWidth - (nDetailedX + nDetailedWidth);
            nDetailedWidth += n;
        }
    }


    y += 120;
    int nInformationX = nDetailedInformationWidth;
    int nInformationWidth = nInformationOneWidth;
    for (int i = 0; i < descriptionList.count(); ++i) {
        QList<QString> list = descriptionList.at(i);

        for (int j = 0; j < list.count(); ++j) {
            pdfGenerator->drawRect(QRect(nInformationX, y, nInformationWidth, 100));
            pdfGenerator->drawText(QRect(nInformationX, y, nInformationWidth, 100), list.at(j),
                                   pdfGenerator->getBaseFont(), QColor(200,0,0));

            nInformationX += nInformationWidth;
            if (list.count()-1 == j + 1) {
                int n = nPdfWidth - (nInformationX + nInformationWidth);
                nInformationWidth += n;
            }
        }

        y += 100;
        nInformationX = nDetailedInformationWidth;
        nInformationWidth = nInformationOneWidth;
    }


    y += 50;
    pdfGenerator->drawPolygon(QRect(600, y, 800, 600));
    pdfGenerator->drawRect(QRect(600, y, 800, 600));

    // 换页
    //    if(y + 100 >= pdfGenerator->getPdfHeight()) {
    //        pdfGenerator->newPage();
    //        y = 10;
    //    }



    pdfGenerator->newPage();
    y = 0;


    /************************************************************************************************************/

    // 外部大矩形框
    pdfGenerator->drawRect(QRect(0, y, nPdfWidth, pdfGenerator->getPdfHeight()), QColor(0,0,0), 8);

    // 左上角m级
    f = pdfGenerator->getBaseFont();
    f.setBold(true);
    f.setPointSize(13);
    pdfGenerator->drawText(QRectF(10, y, 360, 100), "m级:非m", f, QColor(0,0,0), Qt::AlignLeft);


    // 页码
    int pageX = 900;
    f = pdfGenerator->getBaseFont("宋体", 12, 0);
    pdfGenerator->drawText(QRectF(pageX, y, 500, 100), "第 1 页   Page", f, QColor(0,0,0), Qt::AlignLeft);
    y += 80;
    pdfGenerator->drawText(QRectF(pageX, y, 1444, 100), "共 2 页   This report includes page", f, QColor(0,0,0), Qt::AlignLeft);


    y += 100;
    // 标题1
    f = pdfGenerator->getBaseFont("宋体", 20, 8);
    pdfGenerator->drawText(QRectF(0, y, nPdfWidth, 120), "嘻嘻嘻这是一份关于检测相关的世界的详细报告哈哈", f, QColor(0,0,0), Qt::AlignCenter);

    y += 120;
    // 标题1英语
    f = pdfGenerator->getBaseFont("Times New Roman", 11, 8);
    QString english = "abc abc He he he, this is a detailed report about the world related to testing. Ha ha. abc abc";
    pdfGenerator->drawText(QRectF(0, y, nPdfWidth, 120), english, f, QColor(0,0,0), Qt::AlignCenter);



    y += 150;
    // 标题2
    f = pdfGenerator->getBaseFont("宋体", 30, 8);
    pdfGenerator->drawText(QRectF(0, y, nPdfWidth, 130), "一二三四五六报告", f, QColor(0,0,0), Qt::AlignCenter);


    y += 160;
    // 标题2英语
    f = pdfGenerator->getBaseFont("Times New Roman", 20, 12);
    pdfGenerator->drawText(QRectF(0, y, nPdfWidth, 130), "Tihs is a Report", f, QColor(0,0,0), Qt::AlignCenter);


    y += 160;
    // 报告编号
    f = pdfGenerator->getBaseFont("宋体", 10, 0);
    pdfGenerator->drawText(QRectF(0, y, nPdfWidth, 50), "报告编号:( 2025 )报告的 第 15 号", f, QColor(0,0,0), Qt::AlignCenter);


    y += 80;
    // Report No.
    f = pdfGenerator->getBaseFont("Times New Roman", 10, 0);
    pdfGenerator->drawText(QRectF(0, y, nPdfWidth, 50), "Report No.", f, QColor(0,0,0), Qt::AlignCenter);


    int nameX = 200;    // 距离左边的距离
    int lineX = 500;    // 横线距离左边的距离
    int lineWidth = 1322;    // 横线宽度

    y += 100;
    for (int i = 0; i < 6; i++) {
        int tmpY = y + 30;
        // 你的名称
        f = pdfGenerator->getBaseFont();
        pdfGenerator->drawText(QRectF(nameX, y, 250, 60), "你的名称:", f, QColor(0,0,0), Qt::AlignLeft);
        y += 80;
        // 英文
        f = pdfGenerator->getBaseFont("Times New Roman", 10, 0);
        pdfGenerator->drawText(QRectF(nameX, y, 250, 60), "Your name", f, QColor(0,0,0), Qt::AlignLeft);
        y += 70;
        // 画横线
        f = pdfGenerator->getBaseFont();
        pdfGenerator->drawLine(QPointF(lineX, y), QPointF(lineX + lineWidth, y));
        // 画文本
        pdfGenerator->drawText(QRectF(lineX, tmpY, lineWidth, 80), "这是名字呀", f, QColor(0,0,0), Qt::AlignCenter);

        y += 30;

        // 自动换页处理
//        if(y + 200 >= pdfGenerator->getPdfHeight()) {
//            pdfGenerator->newPage();
//            y = 10;
//        }
    }

    y += 50;
    // 签发人
    f = pdfGenerator->getBaseFont();
    pdfGenerator->drawText(QRectF(nameX, y, 400, 60), "签发人:(签字)", f, QColor(0,0,0), Qt::AlignLeft);

    int dataX = 1111;
    // 发证日期
    f = pdfGenerator->getBaseFont();
    pdfGenerator->drawText(QRectF(dataX, y, 400, 60), "发证日期:", f, QColor(0,0,0), Qt::AlignLeft);


    y += 90;
    // 签发人 英文
    f = pdfGenerator->getBaseFont("Times New Roman", 10);
    pdfGenerator->drawText(QRectF(nameX, y, 400, 60), "Signature of leader", f, QColor(0,0,0), Qt::AlignLeft);

    // 发证日期 英文
    f = pdfGenerator->getBaseFont("Times New Roman", 10);
    pdfGenerator->drawText(QRectF(dataX, y, 400, 60), "lssued date", f, QColor(0,0,0), Qt::AlignLeft);


    y += 200;
    // 发证单位
    f = pdfGenerator->getBaseFont();
    pdfGenerator->drawText(QRectF(dataX, y, 600, 60), "发证单位:(盖章位置)", f, QColor(0,0,0), Qt::AlignLeft);

    y += 90;
    // 发证单位 英文
    f = pdfGenerator->getBaseFont("Times New Roman", 10);
    pdfGenerator->drawText(QRectF(dataX, y, 400, 60), "lssued by(stamp)", f, QColor(0,0,0), Qt::AlignLeft);


    y += 200;
    // 地址
    f = pdfGenerator->getBaseFont("宋体", 10);
    f.setBold(true);
    pdfGenerator->drawText(QRectF(nameX, y, 600, 66), "地址(Add):", f, QColor(0,0,0), Qt::AlignLeft);

    f = pdfGenerator->getBaseFont("宋体", 10);
    pdfGenerator->drawText(QRectF(nameX + 330, y, 800, 66), "广东省广州市天河区xx街道xx村xx号", f, QColor(0,0,0), Qt::AlignLeft);

    // 邮编
    f = pdfGenerator->getBaseFont("宋体", 10);
    f.setBold(true);
    pdfGenerator->drawText(QRectF(nameX + 1100, y, 600, 66), "邮编(Post Code):", f, QColor(0,0,0), Qt::AlignLeft);

    f = pdfGenerator->getBaseFont("宋体", 10);
    pdfGenerator->drawText(QRectF(nameX + 1550, y, 300, 66), "123456", f, QColor(0,0,0), Qt::AlignLeft);

    y += 100;
    // 电话
    f = pdfGenerator->getBaseFont("宋体", 10);
    f.setBold(true);
    pdfGenerator->drawText(QRectF(nameX, y, 600, 66), "电话(Tel):", f, QColor(0,0,0), Qt::AlignLeft);

    f = pdfGenerator->getBaseFont("宋体", 10);
    pdfGenerator->drawText(QRectF(nameX + 330, y, 800, 66), "002-123456789", f, QColor(0,0,0), Qt::AlignLeft);

    // 传真
    f = pdfGenerator->getBaseFont("宋体", 10);
    f.setBold(true);
    pdfGenerator->drawText(QRectF(nameX + 800, y, 600, 66), "传真(Fax):", f, QColor(0,0,0), Qt::AlignLeft);

    f = pdfGenerator->getBaseFont("宋体", 10);
    pdfGenerator->drawText(QRectF(nameX + 1050, y, 300, 66), "002-123456789", f, QColor(0,0,0), Qt::AlignLeft);


    y += 100;
    // 电子邮箱
    f = pdfGenerator->getBaseFont("宋体", 10);
    f.setBold(true);
    pdfGenerator->drawText(QRectF(nameX, y, 600, 66), "电子信箱(E-mail):", f, QColor(0,0,0), Qt::AlignLeft);

    f = pdfGenerator->getBaseFont("宋体", 10);
    pdfGenerator->drawText(QRectF(nameX + 400, y, 800, 66), "youxiang666@qq.com", f, QColor(0,0,0), Qt::AlignLeft);


    pdfGenerator->endPage();

    // 通过其它PDF阅读器来打开刚刚绘制的PDF
    QDesktopServices::openUrl(QUrl::fromLocalFile(path));
}

四、源码分享

pdfgenerator.h

#ifndef PDF_GENERATOR_H
#define PDF_GENERATOR_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, QObject *parent = nullptr);
    explicit PdfGenerator(QObject *parent = nullptr);

    ~PdfGenerator();

    qreal getPdfWidth();
    qreal getPdfHeight();


    /**
     * @brief getBaseFont   获得基本的字体
     * @param family
     * @param pointSize
     * @param weight
     * @return
     */
    QFont getBaseFont(const QString &family = "宋体", int pointSize = 12, int weight = -1);

    /**
     * @brief setMargins    设置pdf边距,分别是 左-上-右-下
     * @param left
     * @param top
     * @param right
     * @param bottom
     */
    void setMargins(qreal left, qreal top, qreal right, qreal bottom);

    /**
     * @brief setResolution     设置分辨率,一般为300
     * @param dpi
     */
    void setResolution(int dpi = 300);

    /**
     * @brief newPage           新建下一页
     */
    void newPage();

    /**
     * @brief beginPage         开始绘画
     * @return      成功返回true;失败返回false
     */
    bool beginPage();

    /**
     * @brief endPage           结束会话
     * @return      成功返回true;失败返回false
     */
    bool endPage();

    /**
     * @brief setFileName       设置pdf文件名,内部会open
     * @param fileName
     * @param size
     * @return
     */
    bool setFileName(const QString &fileName, QPagedPaintDevice::PageSize size = QPagedPaintDevice::PageSize::A4);


    /**
     * @brief drawLine  绘制线段
     * @param start     起始坐标
     * @param end       结束坐标
     * @param color     线段颜色
     * @param width     线段宽度
     */
    void drawLine(const QPointF &start, const QPointF &end, const QColor &color = QColor(0,0,0), qreal width = 2);

    /**
     * @brief drawText  绘制文字
     * @param rect      绘制的位置(矩形)
     * @param text      绘制的文本
     * @param font      绘制字体
     * @param color     字体颜色
     * @param align     对齐
     */
    void drawText(const QRectF &rect, const QString &text, const QFont &font, const QColor &color = QColor(0,0,0), Qt::Alignment align = Qt::AlignCenter);

    /**
     * @brief drawImage             绘制图片
     * @param rect                  绘制的位置(矩形)
     * @param imagePath             图片路径
     */
    int drawImage(const QRectF &rect, const QString &imagePath);
    int drawImage(const QRectF &rect, const QPixmap &pixmap);
    int drawImage(const QRectF &rect, const QImage &image);

    /**
     * @brief drawRect          绘制矩形
     * @param rect              绘制的位置(矩形)
     * @param borderColor       边框的颜色
     * @param borderWidth       边框宽度
     * @param fillColor         填充的颜色,默认透明,不填充
     */
    void drawRect(const QRectF &rect, const QColor &borderColor = QColor(0,0,0), qreal borderWidth = 2, const QColor &fillColor = Qt::transparent);

    /**
     * @brief drawEllipse       绘制椭圆
     * @param rect              绘制的位置(矩形)
     * @param borderColor       边框的颜色
     * @param borderWidth       边框宽度
     * @param fillColor         填充的颜色,默认透明,不填充
     */
    void drawEllipse(const QRectF &rect, const QColor &borderColor = QColor(0,0,0), qreal borderWidth = 2, const QColor &fillColor = Qt::transparent);

    /**
     * @brief drawPolygon       画三角形,三角形在矩形区域内
     * @param rect              绘制的位置(矩形)
     * @param borderColor       边框的颜色
     * @param borderWidth       边框宽度
     * @param fillColor         填充的颜色,默认透明,不填充
     */
    void drawPolygon(const QRectF &rect, const QColor &borderColor = QColor(0,0,0), qreal borderWidth = 2, const QColor &fillColor = Qt::transparent);

   // 想设计其他绘制接口继续往下加

private:
    QPdfWriter *m_writer = nullptr;
    QPainter *m_painter = nullptr;
    /// pdf可绘制区域
    QRect m_pageRect;
    /// pdf文件
    QFile m_pdfFile;
};

#endif  // PDF_GENERATOR_H

pdfgenerator.cpp

#include "pdfgenerator.h"
#include <QtDebug>


PdfGenerator::PdfGenerator(const QString &fileName, QPagedPaintDevice::PageSize size, QObject *parent) : QObject (parent)
{
    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(QObject *parent) : QObject (parent)
{

}

PdfGenerator::~PdfGenerator()
{
    if (m_painter) {
        if (m_painter->isActive())
        {
            m_painter->end();
        }
        delete m_painter;
    }

    if (m_writer) {
        m_writer->deleteLater();
    }
}

qreal PdfGenerator::getPdfWidth()
{
    return m_pageRect.width();
}

qreal PdfGenerator::getPdfHeight()
{
    return m_pageRect.height();
}

QFont PdfGenerator::getBaseFont(const QString &family, int pointSize, int weight)
{
    QFont f(family, pointSize, weight);

    return f;
}

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()); // 更新绘制区域
}

void PdfGenerator::setResolution(int dpi)
{
    m_writer->setResolution(dpi);
}

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;
}

bool PdfGenerator::setFileName(const QString &fileName, QPagedPaintDevice::PageSize size)
{
    m_pdfFile.setFileName(fileName);
    // 打开创建并以写的方式打开文件
    if(!m_pdfFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
        return false;
    }

    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());

    return true;
}

// 绘制线段
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();
}

// 绘制图片(根据大小比例,来放大缩小图片)
int PdfGenerator::drawImage(const QRectF &rect, const QString &imagePath)
{
    if (!m_painter->isActive())
        return -10;

    QPixmap pixmap;
    if (!pixmap.load(imagePath)) {
        return -1;
    }

    int nPdfWidth = m_pageRect.width();
    int imageBorder = rect.width();

    float x = (float)(nPdfWidth - imageBorder * 2) / (float)pixmap.width();

    pixmap = pixmap.scaled(nPdfWidth - imageBorder * 2, x * pixmap.height(), Qt::IgnoreAspectRatio);    //根据大小比例,来放大缩小图片

    m_painter->drawPixmap(imageBorder, static_cast<int>(rect.y()), pixmap);

    return pixmap.height();
}

int PdfGenerator::drawImage(const QRectF &rect, const QPixmap &pixmap)
{
    if (!m_painter->isActive())
        return -1;

    if (pixmap.isNull())
        return -1;

    int nPdfWidth = m_pageRect.width();
    int imageBorder = rect.width();

    float x = (float)(nPdfWidth - imageBorder * 2) / (float)pixmap.width();

    QPixmap pixmapTmp = pixmap.scaled(nPdfWidth - imageBorder * 2, x * pixmap.height(), Qt::IgnoreAspectRatio);    //根据大小比例,来放大缩小图片

    m_painter->drawPixmap(imageBorder, static_cast<int>(rect.y()), pixmapTmp);

    return pixmapTmp.height();
}

int PdfGenerator::drawImage(const QRectF &rect, const QImage &image)
{
    if (!m_painter->isActive())
        return -1;

    if (image.isNull())
        return -1;

    int nPdfWidth = m_pageRect.width();
    int imageBorder = rect.width();

    float x = (float)(nPdfWidth - imageBorder * 2) / (float)image.width();

    QImage imageTmp = image.scaled(nPdfWidth - imageBorder * 2, x * image.height(), Qt::IgnoreAspectRatio);    //根据大小比例,来放大缩小图片

    m_painter->drawImage(rect, image);

    return image.height();
}

// 绘制矩形(支持填充)
void PdfGenerator::drawRect(const QRectF &rect, const QColor &borderColor, qreal borderWidth, const QColor &fillColor)
{
    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 &borderColor, qreal borderWidth, const QColor &fillColor)
{
    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();
}

void PdfGenerator::drawPolygon(const QRectF &rect, const QColor &borderColor, qreal borderWidth, const QColor &fillColor)
{
    if (!m_painter->isActive())
        return;

    QPen pen(borderColor, borderWidth); // 底边线宽为5
    m_painter->setPen(pen);
    QBrush brush(fillColor);
    m_painter->setBrush(brush);

    QPoint points[3] = {
        QPoint(rect.x(), rect.y() + rect.height()), // 左下角点
        QPoint(rect.x() + rect.width(), rect.y() + rect.height()), // 右下角点
        QPoint((rect.width() + rect.x() + rect.x()) / 2, rect.y()) // 上顶点
    };

    m_painter->drawPolygon(points, 3);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2377156.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

linux - 权限的概念

目录 用户权限 超级用户与普通用户的区别 超级用户&#xff08;root&#xff09;&#xff1a; 普通用户&#xff1a; 切换用户身份 使用sudo执行高权限命令 用户管理 用户组管理 文件权限 文件访问者类别 基本权限 权限表示方法 权限修改 chmod chown chgrp u…

【Vue】CSS3实现关键帧动画

关键帧动画 两个重点keyframesanimation子属性 实现案例效果展示&#xff1a; 两个重点 keyframes 和 animation 作用&#xff1a;通过定义关键帧&#xff08;keyframes&#xff09;和动画(animation)规则&#xff0c;实现复杂的关键帧动画。 keyframes 定义动画的关键帧序列…

AD 多层线路及装配图PDF的输出

装配图的输出&#xff1a; 1.点开‘智能PDF’ 2. 设置显示顶层&#xff1a; 设置显示底层&#xff1a; 多层线路的输出 同样使用‘智能PDF’

MultiTTS 1.7.6 | 最强离线语音引擎,提供多音色无障碍朗读功能,附带语音包

MultiTTS是一款免费且支持离线使用的文本转语音&#xff08;TTS&#xff09;工具&#xff0c;旨在为用户提供丰富的语音包选项&#xff0c;实现多音色无障碍朗读功能。这款应用程序特别适合用于阅读软件中的离线听书体验&#xff0c;提供了多样化的语音选择&#xff0c;使得听书…

基于自校准分数的扩散模型在并行磁共振成像中联合进行线圈灵敏度校正和运动校正|文献速递-深度学习医疗AI最新文献

Title 题目 Joint coil sensitivity and motion correction in parallel MRI with aself-calibrating score-based diffusion model 基于自校准分数的扩散模型在并行磁共振成像中联合进行线圈灵敏度校正和运动校正 01 文献速递介绍 磁共振成像&#xff08;MRI&#xff09;…

OCR发票识别API实现

OCR发票识别API实现 1. 阿里云OCR发票识别2. Tesseract OCR3. 利用java调用大模型进行识别4. 飞桨PaddleOCR 1. 阿里云OCR发票识别 阿里云OCR发票识别 示例&#xff1a; 接口&#xff1a;https://dgfp.market.alicloudapi.com/ocrservice/invoice 参数&#xff1a;{"img&…

实战案例:采集 51job 企业招聘信息

本文将带你从零开始&#xff0c;借助 Feapder 快速搭建一个企业级招聘信息数据管道。在“基础概念”部分&#xff0c;我们先了解什么是数据管道和 Feapder&#xff1b;“生动比喻”用日常场景帮助你快速理解爬虫组件&#xff1b;“技术场景”介绍本项目中如何使用代理等采集策略…

从AlphaGo到ChatGPT:AI技术如何一步步改变世界?

从AlphaGo到ChatGPT&#xff1a;AI技术如何一步步改变世界&#xff1f; 这里给大家分享一个人工智能学习网站。点击跳转到网站。 https://www.captainbed.cn/ccc 前言 在科技发展的历史长河中&#xff0c;人工智能&#xff08;AI&#xff09;技术无疑是最为璀璨的明珠之一。从…

AI 编程革命:腾讯云 CodeBuddy 如何重塑开发效率?

引言 在传统开发流程中&#xff0c;开发者常需依赖 SDK 文档或反复调试来获取云资源信息。而随着 AI 技术爆发式发展&#xff0c;腾讯云推出的 CodeBuddy 正以对话式编程颠覆这一模式 —— 只需自然语言描述需求&#xff0c;即可直接生成可执行代码。作为腾讯混元大模型与 Dee…

星海智算云平台部署GPT-SoVITS模型教程

背景 随着 GPT-SoVITS 在 AI 语音合成领域的广泛应用&#xff0c;越来越多的个人和团队开始关注这项前沿技术。你是否也在思考&#xff0c;如何快速、高效地部署并体验这款强大的声音克隆模型&#xff1f;遗憾的是&#xff0c;许多本地部署方案不仅配置复杂&#xff0c;而且对…

15:00开始面试,15:06就出来了,问的问题有点变态。。。

从小厂出来&#xff0c;没想到在另一家公司又寄了。 到这家公司开始上班&#xff0c;加班是每天必不可少的&#xff0c;看在钱给的比较多的份上&#xff0c;就不太计较了。没想到4月一纸通知&#xff0c;所有人不准加班&#xff0c;加班费不仅没有了&#xff0c;薪资还要降40%…

20250515通过以太网让VLC拉取视熙科技的机芯的rtsp视频流的步骤

20250515通过以太网让VLC拉取视熙科技的机芯的rtsp视频流的步骤 2025/5/15 20:26 缘起&#xff1a;荣品的PRO-RK3566适配视熙科技 的4800W的机芯。 1080p出图预览的时候没图了。 通过105的机芯出图确认 荣品的PRO-RK3566 的硬件正常。 然后要确认 视熙科技 的4800W的机芯是否出…

UE5.3 C++ 房屋管理系统(二)

三.当房屋生成成功&#xff0c;我们就需要把TMap里的数据存到数据库里。不然一点停止运行&#xff0c;就会所以数据都不见了。这里使用DataTable来存储。 1.DataTable是UE常用的表&#xff0c;虽然不是专门用来存档的&#xff0c;但也可以这么用。 DataTable表&#xff0c;实…

VSCode1.101.0便携版|中英文|编辑器|安装教程

软件介绍 Visual Studio Code是微软推出的一个强大的代码编辑器&#xff0c;功能强大&#xff0c;操作简单便捷&#xff0c;还有着良好的用户界面&#xff0c;设计得很人性化&#xff0c;旨在为所有开发者提供一款专注于代码本身的免费的编辑器。 软件安装 1、 下载安装包…

Linux系统发布.net core程序

前端 前端用的Vue3&#xff0c;发布的话需要Nginx下载安装Nginx 麒麟&#xff1a;这里我麒麟用的是桌面版&#xff0c;我直接把操作流程写在下面&#xff0c;写的比较简单&#xff0c;具体的可以具体搜这一块内容学习一下。打包vue程序&#xff0c;通过MobaXterm将打包后的程序…

极新携手火山引擎,共探AI时代生态共建的破局点与增长引擎

在生成式AI与行业大模型的双重驱动下&#xff0c;人工智能正以前所未有的速度重构互联网产业生态。从内容创作、用户交互到商业决策&#xff0c;AI技术渗透至产品研发、运营的全链条&#xff0c;推动效率跃升与创新模式变革。然而&#xff0c;面对AI技术迭代的爆发期&#xff0…

对比 HTTP-REST 与 gRPC:各自的优缺点以及适用的场景

文章目录 对比 HTTP-REST 与 gRPC&#xff1a;各自的优缺点以及适用的场景HTTP-REST 与 gRPC 的核心区别gRPC 的优缺点HTTP-REST 的优缺点适用场景 模糊点什么是 Protobuf&#xff1f;HTTP/2 会将 HTTP 消息拆分并封装为二进制帧&#xff0c;那还能过使用 HTTP/2 构建 RESTful …

Git - 1( 14000 字详解 )

一&#xff1a; Git 初识 1.1 提出问题 在工作或学习中&#xff0c;我们常常会面临文档管理的问题&#xff0c;尤其是在编写各种文档时。为了防止文档丢失或因更改失误而无法恢复&#xff0c;我们常常会创建多个版本的副本&#xff0c;例如&#xff1a;“报告-v1”、“报告-v…

TCPIP详解 卷1协议 九 广播和本地组播(IGMP 和 MLD)

9.1——广播和本地组播&#xff08;IGMP 和 MLD&#xff09; IPv4可以使用4种IP地址&#xff1a;单播&#xff08;unicast&#xff09;、任播&#xff08;anycast&#xff09;、组播&#xff08;multicast&#xff09;和广播&#xff08;broadcast&#xff09;。 IPv6可以使用…

16.1 - VDMA视频转发实验之TPG

文章目录 1 实验任务2 系统框图3 硬件设计3.1 IP核配置3.2 注意事项 4 软件设计4.1 注意事项4.2 工程源码4.2.1 main.c文件 1 实验任务 基于14.1&#xff0c;使用Xilinx TPG&#xff08;Test Pattern Generator&#xff09; IP提供视频源&#xff0c;将视频数据通过VDMA写入PS…