044_第三代软件开发-保存PDF

头图

第三代软件开发-保存PDF

文章目录

  • 第三代软件开发-保存PDF
    • 项目介绍
    • 保存PDF
      • 头文件
      • 源文件
      • 使用

关键字: QtQmlpdfpainter打印

项目介绍

欢迎来到我们的 QML & C++ 项目!这个项目结合了 QML(Qt Meta-Object Language)和 C++ 的强大功能,旨在开发出色的用户界面和高性能的后端逻辑。

在项目中,我们利用 QML 的声明式语法和可视化设计能力创建出现代化的用户界面。通过直观的编码和可重用的组件,我们能够迅速开发出丰富多样的界面效果和动画效果。同时,我们利用 QML 强大的集成能力,轻松将 C++ 的底层逻辑和数据模型集成到前端界面中。

在后端方面,我们使用 C++ 编写高性能的算法、数据处理和计算逻辑。C++ 是一种强大的编程语言,能够提供卓越的性能和可扩展性。我们的团队致力于优化代码,减少资源消耗,以确保我们的项目在各种平台和设备上都能够高效运行。

无论您是对 QML 和 C++ 开发感兴趣,还是需要我们为您构建复杂的用户界面和后端逻辑,我们都随时准备为您提供支持。请随时联系我们,让我们一同打造现代化、高性能的 QML & C++ 项目!

重要说明☝

☀该专栏在第三代软开发更新完将涨价

保存PDF

这个其实如果是QWidget开发,那就很简单了,直接有现成的打印模块,但是QML下是没有的,这里就需要重新写一下,首先,还是需要我们使用Qt的打印模块,

QT += printsupport 

这里需要说明一下,这个文件不是原创,是在GitHub上找到另一个,完了做了修改。

头文件

#ifndef XXXX_PRINT_H
#define XXXX_PRINT_H#include <QObject>
#ifndef QT_NO_PRINTER
#include <QPrinter>
#include <QPrintDialog>
#endif
#include <QQuickItem>
#include <QJSValue>
#include <QDir>class XXXX_Print : public QQuickItem
{Q_OBJECT
//    QML_ELEMENTQ_DISABLE_COPY(XXXX_Print)public:typedef enum { Print, PrintToFile, GrabOnly } GrabMode;Q_ENUMS(GrabMode);private:QSharedPointer<QQuickItemGrabResult> m_result;// 打印的qml组件QQuickItem *m_item;
#ifndef QT_NO_PRINTERQPrintDialog    *m_printDialogue;QPrinter        *m_printer;bool            m_pagePrinted;bool            m_sessionOpen;// 指定调用“print()”将产生多少份副本int             m_copyCount;QPainter        *m_painter;// 启用或禁用抗锯齿bool    m_antialias;// 启用或禁用单色打印(例如,热敏打印机)bool    m_monochrome;// 选择“打印到文件”时要打印到的文件路径(在某些平台上)QString m_filepath;QRectF  m_margins;
#endifGrabMode    m_mode;QString     m_fileDest;QString     m_fileType;int         m_fileQuality;QJSValue    m_callback;Q_PROPERTY(QQuickItem* item READ getItem WRITE setItem NOTIFY itemChanged)
#ifndef QT_NO_PRINTERQ_PROPERTY(QString filepath READ getFilePath WRITE setFilePath NOTIFY filePathChanged)Q_PROPERTY(QString fileDest READ fileDest WRITE setFileDest NOTIFY fileDestChanged)Q_PROPERTY(bool antialias READ getAntialias WRITE setAntialias NOTIFY antialiasChanged)Q_PROPERTY(bool monochrome READ getMonochrome WRITE setMonochrome NOTIFY monochromeChanged)// 打印的 dpi  整数分辨率Q_PROPERTY(int resolution READ getResolution WRITE setResolution NOTIFY resolutionChanged)Q_PROPERTY(int copyCount READ getCopyCount WRITE setCopyCount NOTIFY copyCountChanged)// QRectF 对象,表示以设备像素为单位的页面尺寸Q_PROPERTY(QRectF pageRect READ getPageRect NOTIFY sizeChanged)Q_PROPERTY(QRectF paperRect READ getPaperRect NOTIFY sizeChanged)Q_PROPERTY(QStringList paperSizes READ getPaperSizes)Q_PROPERTY(QString printerName READ getPrinterName WRITE setPrinterName NOTIFY printerNameChanged)Q_PROPERTY(Status status READ getStatus)
#endifpublic:XXXX_Print(QQuickItem *parent = 0);~XXXX_Print();#ifndef QT_NO_PRINTERtypedef enum {Millimeter = QPageSize::Millimeter,Point = QPageSize::Point,Inch = QPageSize::Inch,Pica = QPageSize::Pica,Didot = QPageSize::Didot,Cicero = QPageSize::Cicero,DevicePixel} Unit;Q_ENUMS(Unit)typedef enum {Idle = QPrinter::Idle,Active = QPrinter::Active,Aborted = QPrinter::Aborted,Error = QPrinter::Error,Unknown} Status;Q_ENUMS(Status)
#endifpublic slots:
#ifndef QT_NO_PRINTERbool print(QJSValue callback=QJSValue());bool setup(bool bDialogue = false);bool open();bool close();bool newPage() const;bool abort();
#endifbool grabImage(const QString &fileFormat, int quality=100, QJSValue callback=QJSValue());bool saveImage(const QString &fileName, const QString &fileFormat, int quality, QJSValue callback=QJSValue());// Property Hooks:void setItem( QQuickItem *item );
#ifndef QT_NO_PRINTERvoid setFilePath(const QString &filepath);void setFileDest(const QString &newFileDest);void setMonochrome(bool toggle);void setAntialias(bool toggle);void setMargins(double top, double right, double bottom, double left);bool setPageSize( qreal width, qreal height, Unit unit );bool setPageSize( const QString &paperSize );void setPrinterName(const QString &printerName);void setResolution(int dpi);void setCopyCount(int count);
#endifQQuickItem *getItem() const { return m_item; }
#ifndef QT_NO_PRINTERQString getFilePath() const { return m_filepath; }const QString fileDest() const { return m_fileDest; };bool getMonochrome() const { return m_monochrome; }bool getAntialias() const { return m_antialias; }QRectF getMargins() const { return m_margins; }QRectF getPageRect(Unit unit=DevicePixel) const;QRectF getPaperRect(Unit unit=DevicePixel) const;QStringList getPaperSizes() const;QString getPrinterName() const;int getResolution() const { return m_printer->resolution(); }int getCopyCount() const { return m_printer->copyCount(); }Status getStatus() const;
#endifprivate slots:bool grab();void grabbed();private:bool printGrab(const QImage &img);bool isDirExist(QString fullPath);signals:void itemChanged();void frameGrabbed(const QByteArray &imageData);void sizeChanged();void printComplete();void printError();
#ifndef QT_NO_PRINTERvoid filePathChanged();void monochromeChanged();void antialiasChanged();void marginsChanged();void printerNameChanged();void resolutionChanged();void copyCountChanged();
#endifvoid fileDestChanged();void strTestChanged();
};#endif // XXXX_PRINT_H

源文件

#include "XXXX_print.h"#include <QBuffer>
#include <QFileInfo>
#include <QPainter>
#ifndef QT_NO_PRINTER
# include <QPrintEngine>
#endif
#include <QQuickItemGrabResult>// Just for converting QByteArray:
#include <QQmlEngine>void XXXX_Print::setFileDest(const QString &newFileDest)
{if (m_fileDest == newFileDest)return;m_fileDest = newFileDest;emit fileDestChanged();
}XXXX_Print::XXXX_Print(QQuickItem *parent):QQuickItem(parent)
{
#ifndef QT_NO_PRINTERm_printDialogue = nullptr;m_printer = new QPrinter(QPrinter::ScreenResolution);m_pagePrinted = false;m_sessionOpen = false;m_copyCount = 1;m_painter = nullptr;m_antialias = true;m_monochrome = false;m_margins = QRectF(0, 0, 0, 0);m_filepath.clear();
#endifm_mode = XXXX_Print::GrabOnly;m_item = NULL;m_fileDest.clear();m_fileType.clear();m_fileQuality = 0;
}XXXX_Print::~XXXX_Print()
{
#ifndef QT_NO_PRINTERdelete m_printer;
#endif
}#ifndef QT_NO_PRINTER
/*** @brief XXXX_Print::print  打印/保存PDF(打印 setup至true)* @param callback* @return*/
bool XXXX_Print::print(QJSValue callback)
{m_mode = XXXX_Print::Print;m_callback = callback;return grab();
}
#endif/*** @brief XXXX_Print::grabImage 图片以QByteArray存储* @param fileFormat* @param quality* @param callback* @return*/
bool XXXX_Print::grabImage(const QString &fileFormat, int quality, QJSValue callback)
{m_mode = XXXX_Print::GrabOnly;m_callback = callback;m_fileType = fileFormat;m_fileQuality = quality;return grab();
}/*** @brief XXXX_Print::saveImage   保存图片,不用打开* @param fileName                  图片名称* @param fileFormat                图片类型* @param quality                   图片像素-1 0-100* @param callback* @return*/
bool XXXX_Print::saveImage(const QString &fileName, const QString &fileFormat, int quality, QJSValue callback)
{m_mode = XXXX_Print::PrintToFile;m_callback = callback;m_fileDest = fileName;m_fileType = fileFormat;m_fileQuality = quality;return grab();
}#ifndef QT_NO_PRINTER
/*** @brief XXXX_Print::setup  初始化打印机(true)/存储PDF(false)* @param bDialogue* @return*/
bool XXXX_Print::setup(bool bDialogue)
{m_printer->setOutputFormat(QPrinter::NativeFormat);QMarginsF margins( 0.0, 0.0, 0.0, 0.0);if( !m_printer->setPageMargins( margins, QPageLayout::Millimeter ) ){qWarning() << tr("Printer: Failed to set page margin (in mm) as configured.");return false;}QString strFilePath = QCoreApplication::applicationDirPath();m_printer->setOutputFileName(m_filepath + m_fileDest);   //设置输出路径if(bDialogue){m_printDialogue = new QPrintDialog(m_printer);if( m_printDialogue->exec() == QDialog::Accepted ){m_printDialogue->deleteLater();return true;}qWarning() << "打印机初始化失败";delete m_printDialogue;}else{// HP LaserJet Pro M428f-M429f [453773]m_printer->setOutputFormat(QPrinter::PdfFormat);  //设置输出格式为pdfreturn true;}return false;
}/*** @brief XXXX_Print::open 打开打印机/存储* @return*/
bool XXXX_Print::open()
{if( m_sessionOpen ){qCritical() << tr("Printer::open called while already in a multipage session. (Call 'close' first.)");return false;}m_painter = new QPainter();if( !m_painter ){qCritical() << tr("Printer::open failed to instantiate new QPainter. (Are you out of memory?)");return false;}if(!m_painter->begin(m_printer)){qCritical() << tr("Failed to initialise QPainter to QPrintDevice.");return false;}m_painter->setRenderHint(QPainter::Antialiasing, m_antialias);m_painter->setRenderHint(QPainter::TextAntialiasing, m_antialias);m_painter->setRenderHint(QPainter::SmoothPixmapTransform, m_antialias);m_sessionOpen = true;return true;
}/*** @brief XXXX_Print::close 关闭打印机/存储* @return*/
bool XXXX_Print::close()
{if( !m_sessionOpen ){qCritical() << tr("Printer::close called while not in multipage session.");return false;}delete m_painter;m_painter = nullptr;m_sessionOpen = false;return true;
}/*** @brief XXXX_Print::newPage 下一页* @return*/
bool XXXX_Print::newPage() const
{if( !m_sessionOpen ){qCritical() << tr("Printer::newPage called while not in a multipage session. (Call Printer::open first.)");return false;}return m_printer->newPage();
}/*** @brief XXXX_Print::abort 中止打印机* @return*/
bool XXXX_Print::abort()
{if( m_sessionOpen )close();return m_printer->abort();
}void XXXX_Print::setMonochrome(bool toggle)
{if( m_monochrome == toggle )return;m_monochrome = toggle;emit monochromeChanged();
}void XXXX_Print::setAntialias(bool toggle)
{if( m_antialias == toggle )return;m_antialias = toggle;emit antialiasChanged();
}void XXXX_Print::setFilePath(const QString &filepath)
{if( m_filepath == filepath )return;isDirExist(filepath);m_filepath = filepath;emit filePathChanged();
}
#endifvoid XXXX_Print::setItem(QQuickItem *item)
{if( m_item == item )return;m_item = item;emit itemChanged();
}#ifndef QT_NO_PRINTER
void XXXX_Print::setMargins(double top, double right, double bottom, double left)
{QRectF m( left, top, right-left, bottom-top );if( m_margins == m )return;m_margins = m;emit marginsChanged();
}bool XXXX_Print::setPageSize( const QString &paperSize )
{QPageSize size;// Run through each..for( int x=0; x < QPageSize::LastPageSize; x++ ){size = QPageSize((QPageSize::PageSizeId)x);if( size.name() == paperSize ){bool result = m_printer->setPageSize( size );emit sizeChanged();return result;}}qWarning() << tr("Unknown paper size: ") << paperSize << tr(" (Refer to 'paperSizes()' for valid options.)");return false;
}bool XXXX_Print::setPageSize( qreal width, qreal height, Unit unit )
{QSizeF szf(width, height);QPageSize size;switch( unit ){case DevicePixel:// Fanagle from DPI:szf /= m_printer->resolution();size = QPageSize(szf, QPageSize::Inch);break;default:size = QPageSize(szf, (QPageSize::Unit)unit);break;}bool result = m_printer->setPageSize(size);emit sizeChanged();return result;
}void XXXX_Print::setPrinterName(const QString &printerName)
{if( m_printer->printerName() == printerName )return;m_printer->setPrinterName( printerName );emit printerNameChanged();
}void XXXX_Print::setResolution(int dpi)
{if( m_printer->resolution() == dpi )return;m_printer->setResolution( dpi );emit resolutionChanged();
}void XXXX_Print::setCopyCount(int count)
{if( m_printer->copyCount() == count )return;m_printer->setCopyCount( count );emit copyCountChanged();
}QRectF XXXX_Print::getPageRect(Unit unit) const
{return m_printer->pageRect( (QPrinter::Unit)unit );
}QRectF XXXX_Print::getPaperRect(Unit unit) const
{return m_printer->paperRect( (QPrinter::Unit)unit );
}QStringList XXXX_Print::getPaperSizes() const
{QStringList results;QPageSize size;// Run through each..for( int x=0; x < QPageSize::LastPageSize; x++ ){size = QPageSize((QPageSize::PageSizeId)x);results.append( size.name() );}return results;
}XXXX_Print::Status XXXX_Print::getStatus() const
{QPrinter::PrinterState state = m_printer->printEngine()->printerState();return (XXXX_Print::Status)state;
}
#endifbool XXXX_Print::grab()
{if( !m_item ){qWarning() << tr("Printer::grab: No item source specified. (Set it with the 'item' property.)");return false;}QSharedPointer<QQuickItemGrabResult> res = m_item->grabToImage();if( !res ){qWarning() << tr("Printer::grab: Grab failed for some reason. (Is the item loaded and rendered?)");return false;}connect( res.data(), SIGNAL(ready()), this, SLOT(grabbed()) );m_result = res;return true;
}#ifndef QT_NO_PRINTER
bool XXXX_Print::printGrab(const QImage &img)
{if( !m_sessionOpen ){qCritical() << tr("Printer: Attempt to print without first calling Printer::open(). (This behaviour changed in 1.2)");;return false;}if( m_monochrome )m_painter->drawImage( m_printer->paperRect(QPrinter::DevicePixel), img.convertToFormat(QImage::Format_Mono, Qt::MonoOnly | Qt::ThresholdDither) );elsem_painter->drawImage( m_printer->paperRect(QPrinter::DevicePixel), img );return true;
}/*** @brief XXXX_Print::isDirExist 判断文件夹是否存在,不存在则创建* @param fullPath* @return*/
bool XXXX_Print::isDirExist(QString fullPath)
{
//    QString strFilePath = QCoreApplication::applicationDirPath();QDir dir(fullPath);if(dir.exists()){return true;}else{return dir.mkdir(fullPath);}
}
#endifvoid XXXX_Print::grabbed()
{const QImage img = m_result.data()->image();m_result.clear();QQmlEngine *jse = qmlEngine(this);jse->collectGarbage();bool ret = true;if( m_mode == XXXX_Print::PrintToFile ){ret = img.save(m_fileDest, m_fileType.toStdString().c_str(), m_fileQuality);if( m_callback.isCallable() ){QJSValueList args;args << ret;m_callback.call(args);}}
#ifndef QT_NO_PRINTERelse if( m_mode == XXXX_Print::Print ){ret = printGrab(img);if( m_callback.isCallable() ){QJSValueList args;args << ret;m_callback.call(args);}}
#endifelse if( m_callback.isCallable() ){QImage image;QByteArray ba;QBuffer buffer(&ba);buffer.open(QIODevice::WriteOnly);// 此函数将 QImage 写入给定设备ret = img.save(&buffer, m_fileType.toStdString().c_str(), m_fileQuality);buffer.close();if( ret ){QJSValueList args;args << jse->toScriptValue<QByteArray>(ba);m_callback.call( args );}}//    m_callback = QJSValue();if( ret )emit printComplete();elseemit printError();
}#ifndef QT_NO_PRINTER
QString XXXX_Print::getPrinterName() const
{return m_printer->printerName();
}
#endif

使用

    XXX_Print {id: printPDFfilepath: pdfFilePathfileDest: "/" + UserProfile.userName + dateString +".pdf"antialias: falsemonochrome: falseonPrintComplete: console.log("Print complete.");onPrintError: console.log("Print error!");Component.onCompleted: scanPaperSizes();function scanPaperSizes(){printPDF.setPageSize( 'A4' );printPDF.setMargins(0,0,0,0)}}

博客签名2021

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

swift语言用哪种库适合做爬虫?

目录 1、Alamofire 2、URLSession 3、YepHttp 4、Kickbox 5、Vapor 注意事项 总结 在Swift语言中&#xff0c;可以使用第三方库来帮助进行网络爬虫的开发。以下是几个适合Swift语言使用的爬虫库&#xff0c;以及相应的代码示例&#xff1a; 1、Alamofire Alamofire是Sw…

RK3568平台开发系列讲解(音视频篇)RTMP 推流

🚀返回专栏总目录 文章目录 一、RTMP 的工作原理二、RTMP 流媒体服务框架2.1、Nginx 流媒体服务器2.2、FFmpeg 推流沉淀、分享、成长,让自己和他人都能有所收获!😄 📢目前常见的视频监控和视频直播都是使用了 RTMP、RTSP、HLS、MPEG-DASH、 WebRTC流媒体传输协议等。 R…

C语言之pthread_once实例总结(八十三)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

从TCP到Socket,彻底理解网络编程是怎么回事

进行程序开发的同学&#xff0c;无论Web前端开发、Web后端开发&#xff0c;还是搜索引擎和大数据&#xff0c;几乎所有的开发领域都会涉及到网络编程。比如我们进行Web服务端开发&#xff0c;除了Web协议本身依赖网络外&#xff0c;通常还需要连接数据库&#xff0c;而数据库连…

Java中对象的比较:复写基类的equals+Comparble接口类的比较+比较器比较+PriorityQueue的比较+源码分析

文章目录 Java中对象的比较一、元素的比较二、对象的比较1.复写基类的equals2.基于Comparble接口类的比较3.基于比较器比较三种方法的对比 4. 集合框架中PriorityQueue的比较方式 Java中对象的比较 一、元素的比较 在Java中&#xff0c;基本类型的对象可以直接比较大小。 二、…

【Python3】【力扣题】232. 用栈实现队列

【力扣题】题目描述&#xff1a; 栈&#xff1a;线性集合。后进先出。 队列&#xff1a;线性集合。先进先出。 【Python3】代码&#xff1a; 解题思路&#xff1a;两个栈&#xff0c;一个入队的栈&#xff0c;一个出队的栈。出栈时&#xff0c;若出队的栈为空&#xff0c;才将…

RabbitMQ 死信队列

在MQ中&#xff0c;当消息成为死信&#xff08;Dead message&#xff09;后&#xff0c;消息中间件可以将其从当前队列发送到另一个队列中&#xff0c;这个队列就是死信队列。而在RabbitMQ中&#xff0c;由于有交换机的概念&#xff0c;实际是将死信发送给了死信交换机&#xf…

c语言 结构体 简单实例

结构体 简单例子 要求&#xff1a; 结构体保存学生信息操作 代码 #include <stdio.h>//定义结构体 struct student{int ID;char name[20];char sex;char birthday[8];int grade; };int main(){int number;printf("请输入学生个数&#xff1a;");scanf(&quo…

lua中的循环 while、for、repeat until三种循环方式、pairs和ipairs区别

lua中的循环 while、for、repeat until三种循环方式、pairs和ipairs区别 介绍for循环参数ipairs和pairs whilerepeat until总结 介绍 这里我用while、for、repeat until分别输出1-20之间的奇数 &#xff0c;具体的语法可以看下面的代码 for循环 参数 定义一个初始值为start…

ARM64 linux并发与同步之原子操作

卷2&#xff1a;调试与案例分析 第一章 并发与同步 画了两张简图&#xff0c;方便理解&#xff0c;如下&#xff1a; 针对并发源的问题&#xff0c;我接触的项目中都是SMP系统&#xff0c;目前大部分也都是SMP系统&#xff1b; 对于SMP系统&#xff0c;情况会更复杂。 □ 同…

Servlet详解

一.Servlet生命周期 初始化提供服务销毁 1.测试生命周期 package com.demo.servlet;import javax.servlet.*; import java.io.IOException;public class LifeServlet implements Servlet {Overridepublic void init(ServletConfig servletConfig) throws ServletException {…

ros的安装和rosdep的初始化操作

ros的安装 安装ROS完整桌面版安装&#xff08;Desktop-Full&#xff09;环境配置rosdep初始化 安装ROS完整桌面版安装&#xff08;Desktop-Full&#xff09; 官网 选择思想者乌龟 选择ubuntu平台 操作 开始安装ROS 完整桌面版安装&#xff08;Desktop-Full&#xff0c;推荐…