【Qt开发流程】之打印文档

news2024/12/24 17:58:04

描述

Qt为打印提供了广泛的跨平台支持。使用每个平台上的打印系统,Qt应用程序可以打印到连接的打印机上,也可以通过网络打印到远程打印机上。Qt的打印系统还支持PDF文件生成,为基本报表生成工具提供了基础。

支持打印的类

下面的类支持选择和设置打印机和打印输出。

作用
QAbstractPrintDialog用于配置打印机的打印对话框的基本实现
QPageSetupDialog配置对话框,用于打印机上与页面相关的选项
QPrintDialog用于指定打印机配置的对话框
QPrintPreviewDialog用于预览和配置打印机输出的页面布局的对话框
QPrintEngine定义QPrinter与给定打印子系统交互的接口
QPrinter在打印机上作画的装置
QPrinterInfo提供对现有打印机信息的访问
QPrintPreviewWidget用于预览打印机输出的页面布局的小部件

打印设备

在Qt中,打印机由QPrinter表示,QPrinter是一个绘图设备,它提供了特定于打印的功能,例如支持多页和双面输出。因此,打印需要使用QPainter在一系列页面上进行绘制,就像在自定义小部件或图像上进行绘制一样。

创建一个QPrinter

虽然QPrinter对象可以在不需要用户输入的情况下构造和设置,但打印通常是作为用户请求的结果执行的;例如,当用户选择File|Print…菜单项。在这种情况下,一个新构造的QPrinter对象被提供给QPrintDialog,允许用户指定要使用的打印机、纸张大小和其他打印属性。

          QPrinter printer;

          QPrintDialog dialog(&printer, this);
          dialog.setWindowTitle(tr("Print Document"));
          if (editor->textCursor().hasSelection())
              dialog.addEnabledOption(QAbstractPrintDialog::PrintSelection);
          if (dialog.exec() != QDialog::Accepted) {
              return;
          }

在将QPrinter提供给打印对话框之前,也可以通过修改它来设置某些默认属性。例如,生成批量报告用于打印的应用程序可以将QPrinter设置为默认情况下写入本地文件,而不是写入打印机。

打印页

一旦构造并设置了QPrinter对象,就可以使用QPainter对其执行绘画操作。可以通过以下方式来建构和设置一个画家:

      QPrinter printer(QPrinter::HighResolution);
      printer.setOutputFileName("print.ps");
      QPainter painter;
      painter.begin(&printer);

      for (int page = 0; page < numberOfPages; ++page) {

          // Use the painter to draw on the page.

          if (page != lastPage)
              printer.newPage();
      }

      painter.end();

由于QPrinter从空白页开始,只需要在绘制每个页面后调用newPage()函数,最后一页除外。
当调用end()时,文档被发送到打印机或写入到本地文件。

坐标系统

QPrinter提供的函数可用于获取有关纸张尺寸(纸张矩形)和可打印区域尺寸(页面矩形)的信息。这些是在逻辑设备坐标中给出的,可能与设备本身使用的物理坐标不同,这表明打印机能够以比用户显示器更高的分辨率呈现文本和图形。
虽然不需要自己处理逻辑和物理坐标之间的转换,但仍然需要将转换应用于绘制操作,因为用于在屏幕上绘制的像素测量值对于典型打印机的高分辨率来说通常太小。

  • 打印机和画家坐标系统

paperRect()和pag竖立()函数提供有关用于打印的纸张的大小和可以在其上绘制的区域的信息。
pag竖立()返回的矩形通常位于paperRect()返回的矩形内。当使用QPainter和QPrinter作为底层绘画设备时,不需要考虑这些区域的位置和大小;绘制器坐标系统的原点将与页面矩形的左上角重合,绘制操作将被剪切到页面可绘制部分的边界上。

在这里插入图片描述
绘制文本时,绘制系统会自动使用正确的设备度量,但是,如果需要使用从字体度量获得的信息来定位文本,则需要确保在构造QFontMetrics和QFontMetricsF对象时指定了打印设备,或者确保使用的每个QFont都是使用接受QPaintDevice参数的构造函数的形式构造的。

打印控件

要打印小部件,可以使用QWidget::render()函数。如前所述,打印机的分辨率通常高于屏幕分辨率,因此必须缩放打印对象。可能还想在页面上定位小部件。下面的代码示例显示了这可能是什么样子。

          QPainter painter;
          painter.begin(&printer);
          double xscale = printer.pageRect().width()/double(myWidget->width());
          double yscale = printer.pageRect().height()/double(myWidget->height());
          double scale = qMin(xscale, yscale);
          painter.translate(printer.paperRect().x() + printer.pageRect().width()/2,
                             printer.paperRect().y() + printer.pageRect().height()/2);
          painter.scale(scale, scale);
          painter.translate(-width()/2, -height()/2);

          myWidget->render(&painter);

这将使小部件在页面上居中并缩放,使其适合页面。

从复杂小部件打印

某些小部件,如QTextEdit和QGraphicsView,显示丰富的内容,这些内容通常由其他类的实例管理,如QTextDocument和QGraphicsScene。因此,通常是这些内容处理类通过可用于执行完整任务的函数或通过接受现有QPainter对象的函数提供打印功能。一些小部件提供了方便的函数来公开底层打印特性,从而避免了为了调用单个函数而获取内容处理程序的需要。
下表显示了哪个类和函数负责从选择的不同小部件中进行打印。对于不直接公开打印功能的小部件,可以通过相应小部件API中的函数获得包含该功能的内容处理类。
在这里插入图片描述
QTextEdit需要QPrinter而不是QPainter,因为它使用有关配置页面尺寸的信息,以便在打印文档中最合适的位置插入分页符。

示例

UI:
在这里插入图片描述
需要在.pro中添加:

QT += printsupport

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

class QPrinter;

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

public slots:
    void doPrint();
    void doPrintPreview();
    void printPreview(QPrinter *painter);
    void createPDF();

private slots:
    void on_action_print_triggered();

    void on_action_printPreview_triggered();

    void on_action_create_triggered();

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QPrinter>
#include <QtPrintSupport/QPrintDialog>
#include <QtPrintSupport/QPrintPreviewDialog>
#include <QFileDialog>
#include <QFileInfo>

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

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

void MainWindow::doPrint()
{
    QPrinter printer;
    QPrintDialog dlg(&printer, this);
    if(ui->textEdit->textCursor().hasSelection())
    {
        dlg.addEnabledOption(QAbstractPrintDialog::PrintSelection);
    }

    if(QDialog::Accepted == dlg.exec())
    {
        ui->textEdit->print(&printer);
    }
}

void MainWindow::doPrintPreview()
{
    QPrinter printer;
    QPrintPreviewDialog preview(&printer, this);
    connect(&preview, &QPrintPreviewDialog::paintRequested, this, &MainWindow::printPreview);

    preview.exec();
}

void MainWindow::printPreview(QPrinter *printer)
{
    ui->textEdit->print(printer);
}

void MainWindow::createPDF()
{
    QString strFileName = QFileDialog::getSaveFileName(this, "exportPDF", "./", "*.pdf");
    if(!strFileName.isEmpty())
    {
        if(QFileInfo(strFileName).suffix().isEmpty())
        {
            strFileName.append(".pdf");
        }
        QPrinter printer;
        printer.setOutputFormat(QPrinter::PdfFormat);
        printer.setOutputFileName(strFileName);
        ui->textEdit->print(&printer);
    }
}

void MainWindow::on_action_print_triggered()
{
    doPrint();
}

void MainWindow::on_action_printPreview_triggered()
{
    doPrintPreview();
}

void MainWindow::on_action_create_triggered()
{
    createPDF();
}

结果截图

在这里插入图片描述
在这里插入图片描述

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

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

相关文章

【c++|SDL】三、画图类抽象

every blog every motto: You can do more than you think. https://blog.csdn.net/weixin_39190382?typeblog 0. 前言 1. 画图类抽象 之前将画图&#xff08;显示图像&#xff09;放在Game.cpp中,现在将其单独放在一个类中, 编译运行为&#xff1a; g m14main.cpp Game.…

Course1-Week3-分类问题

Course1-Week3-分类问题 文章目录 Course1-Week3-分类问题1. 逻辑回归1.1 线性回归不适用于分类问题1.2 逻辑回归模型1.3 决策边界 2. 逻辑回归的代价函数3. 实现梯度下降4. 过拟合与正则化4.1 线性回归和逻辑回归中的过拟合4.2 解决过拟合的三种方法4.3 正则化4.4 用于线性回归…

C语言之结构体详解

C语言之结构体详解 文章目录 C语言之结构体详解1. 结构体类型的声明2. 结构体变量的创建和初始化3. 结构体的特殊声明4. 结构体的自引用结构体的自引用匿名结构体的自引用 5. 结构体内存对齐5.1 练习一5.2 练习三 6. 为什么存在内存对⻬? 1. 结构体类型的声明 struct tag {me…

【Web】UUCTF 2022 新生赛 个人复现

目录 ①websign ②ez_rce ③ez_upload ④ez_unser ⑤ezsql ⑥ezpop ⑦funmd5 ⑧phonecode ⑨ezrce ①websign 右键打不开&#xff0c;直接抓包发包看源码 ②ez_rce “反引号” 在PHP中会被当作SHELL命令执行 ?codeprintf(l\s /); ?codeprintf(ta\c /ffffffffffl…

leetCode 131.分割回文串 + 动态规划 + 回溯算法 + 优化 + 图解 + 笔记

我的往期文章&#xff1a; leetCode 647.回文子串 动态规划 优化空间 / 中心扩展法 双指针-CSDN博客https://blog.csdn.net/weixin_41987016/article/details/133883091?spm1001.2014.3001.5501leetCode 131.分割回文串 回溯算法 图解 笔记-CSDN博客https://blog.csdn.n…

有什么值得推荐的node. js练手项目吗?

前言 可以参考一下下面的nodejs相关的项目&#xff0c;希望对你的学习有所帮助&#xff0c;废话少说&#xff0c;让我们直接进入正题 1、 NodeBB Star: 13.3k 一个基于Node.js的现代化社区论坛软件&#xff0c;具有快速、可扩展、易于使用和灵活的特点。它支持多种数据库&…

在Windows中加密文件或文件夹不需要太大的努力就可以实现,主要有两种加密方法

如果你正在寻找一种在Windows计算机上保持文件和文件夹隐私的简单方法,你有几个选择。 得益于Microsoft Office Suite,你可以使用内置的加密功能对Office文件(如Word文档或PowerPoint演示文稿)进行密码保护。 一些Windows操作系统还配备了加密文件系统(EFS),可以对任何…

Set集合的特点

Set系列集合特点&#xff1a; 无序&#xff1a;添加数据的顺序和获取出的数据顺序不一致&#xff1b;不重复&#xff1b;无索引&#xff1b; HashSet&#xff1a;无序&#xff0c;不重复&#xff0c;无索引 LinkedHashSet&#xff1a;有序&#xff0c;不重复&#xff0c;无索引…

python进阶技巧

1.闭包 通过函数嵌套&#xff0c;可以让内部函数依赖外部变量&#xff0c;可以避免全局变量的污染问题 闭包注意事项&#xff1a; 总结&#xff1a; 2.装饰器 2.1装饰器的一般写法 2.2 装饰器的语法糖写法 def outer(func):def inner():print(睡了)func()print(起床)retur…

Zookeeper从零入门笔记

Zookeeper从零入门笔记 一、入门1. 概述2. 特点3. 数据结构4. 应用场景 二、本地1.安装2. 参数解读 三、集群操作3.1.1 集群安装3.2 选举机制1. 第一次启动2. 非第一次启动 3.3 ZK集群启动停止脚本3.4 客户端命令行操作3.2.1 命令行语法3.2.2 节点类型&#xff08;持久/短暂/有…

飞致云开源社区月度动态报告(2023年11月)

自2023年6月起&#xff0c;中国领先的开源软件公司FIT2CLOUD飞致云以月度为单位发布《飞致云开源社区月度动态报告》&#xff0c;旨在向广大社区用户同步飞致云旗下系列开源软件的发展情况&#xff0c;以及当月主要的产品新版本发布、社区运营成果等相关信息。 飞致云开源大屏…

传统算法:使用 Pygame 实现选择排序

使用 Pygame 模块实现了选择排序的动画演示。首先,它生成一个包含随机整数的数组,并通过 Pygame 在屏幕上绘制这个数组的条形图。接着,通过选择排序算法对数组进行排序,动画效果可视化每一步的排序过程。在排序的过程中,程序找到未排序部分的最小元素,并将其与未排序部分…

如何获取阿里巴巴中国站按图搜索1688商品(拍立淘) API接口(item_search_img-按图搜索1688商品(拍立淘))

一、背景介绍 阿里巴巴中国站作为中国领先的B2B电子商务平台&#xff0c;提供了大量的商品信息和交易服务。其中&#xff0c;按图搜索1688商品&#xff08;拍立淘&#xff09;是阿里巴巴中国站特有的功能之一&#xff0c;它可以通过上传图片来搜索与图片相似的商品&#xff0c…

Js页面录屏切片存储数据上传后端

前端 screenShot(){// 获取屏幕共享流navigator.mediaDevices.getDisplayMedia({video: true,audio: true,//preferCurrentTab 共享本次操作的页面preferCurrentTab: true}).then(async stream > {const mediaRecorder new MediaRecorder(stream, { mimeType: video/webm; …

基于AT89C51单片机的秒表设计

1&#xff0e;设计任务 利用单片机AT89C51设计秒表&#xff0c;设计计时长度为9:59:59&#xff0c;超过该长度&#xff0c;报警。创新&#xff1a;设置重启&#xff1b;暂停&#xff1b;清零等按钮。最后10s时播放音乐提示。 本设计是采用AT89C51单片机为中心&#xff0c;利用其…

代码随想录算法训练营第一天 | 704. 二分查找 27. 移除元素

class Solution { public:int search(vector<int>& nums, int target) {int l0;int rnums.size()-1;while(l<r){int mid(lr)>>1;if(targetnums[mid]) return mid;if(target>nums[mid]){lmid1;}else{rmid-1;}}return -1;} }; 之前就已经熟悉二分法了&am…

【Linux】第二十三站:缓冲区

文章目录 一、一些奇怪的现象二、用户级缓冲区三、用户级缓冲区刷新问题四、一些其他问题1.缓冲区刷新的时机2.为什么要有这个缓冲区3.这个缓冲区在哪里&#xff1f;4.这个FILE对象属于用户呢&#xff1f;还是操作系统呢&#xff1f;这个缓冲区&#xff0c;是不是用户级的缓冲区…

Linux实现类似cp的命令

1.利用主函数的三个函数进行传参 1).主函数的三个参数的含义: argc:主函数的参数个数 argv:主函数的参数内容 envp:环境变量; 2).演示代码: #include <stdio.h> #include <stdlib.h> #include <unistd.h> int main(int argc,char *argv[],char *envp[]…

Vue3.x 中 hooks 函数封装和使用

一、hooks 是什么 vue3 中的 hooks 就是函数的一种写法&#xff0c;就是将文件的一些单独功能的 js 代码进行抽离出来进行封装使用。 它的主要作用是 Vue3 借鉴了 React 的一种机制&#xff0c;用于在函数组件中共享状态逻辑和副作用&#xff0c;从而实现代码的可复用性。 注…

[笔记]dubbo发送接收

个人笔记 consumer 主要使用ThreadlessExecutor实现全consumer的全双工通讯。consumer创建本次请求的requestId用于将response和request匹配。 然后分以下几步完成一次请求发送并接收结果&#xff1a; 槽&#xff1a;发送消息前将用于接收结果的executor放到一个map中存储 发…