描述
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_OBJECTpublic: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();
}
结果截图