QPainter是可以在QPrinter上绘制图形和文字的,利用这个方法,可以绘制任何图形或者文字、表格等,可以实现复杂的表格绘制,如果报表比较特殊,可以尝试使用这个方法,下面简单介绍一下实现的过程。
实现简介
我这边里封装了一个报表打印类,用于打印报表,当前并没有传入数据和参数,实际实际项目是需要传入参数和数据的。
首先是打印的接口代码:
- 1 void printWithPreview();
- 2 void printDirect();
- 3 void printOnePage(QPainter *painter, int no);
printWithPreview 是用于调出打印预览窗口;
printDirect 是直接打印
printOnePage 是打印一页;因为可能会打印多个页,所以这里把一页的绘制单独封装为一个函数
打印信号处理槽函数,用于接收打印信号,在这个函数里调用printOnePage去绘制要打印的报表。
1 void printDocument(QPrinter *printer);
打印版式设置
横向打印和纵向打印;
打印方向 Portrait 纵向,Landscape:横向
使用如下函数设置
- 1enum Orientation { Portrait, Landscape };
- 2void setOrientation(Orientation);
代码
头文件:
- 1#ifndef CTESTREPORT_H
- 2#define CTESTREPORT_H
- 3
- 4#include <QObject>
- 5#include <QAbstractItemModel>
- 6#include <QPrinter>
- 7#include <QVariantMap>
- 8#include <QVariantList>
- 9
- 10class CTestReport:public QObject
- 11{
- 12 Q_OBJECT
- 13public:
- 14 explicit CTestReport(QObject *parent = nullptr);
- 15 virtual ~CTestReport();
- 16
- 17
- 18
- 19 void printWithPreview();
- 20 void printDirect();
- 21 void printOnePage(QPainter *painter, int no);
- 22
- 23private:
- 24 void drawTable(QPainter *painter, int no);
- 25signals:
- 26
- 27public slots:
- 28
- 29private slots:
- 30 void printDocument(QPrinter *printer);
- 31
- 32private:
- 33
- 34 int m_startx; //整体表格在A4纸中的起始x坐标
- 35 int m_starty; //整体表格在A4纸中的起始y坐标
- 36 int m_width; //整体表格的宽
- 37 int m_height; //整体表格的高
- 38
- 39 int m_titleHeight; //标题栏的高
- 40
- 41 int m_colNum ; //表格的总列数
- 42 int m_rowNum ; //表格的总行数
- 43 int m_rowHeight; //单元表格高
- 44 int m_colWidth; //单元表格宽
- 45
- 46};
- 47
- 48
- 49#endif // CTESTREPORT_H
类实现源文件:
- 1#include <QPrintPreviewDialog>
- 2#include <QPrintDialog>
- 3#include <QPrinter>
- 4#include <QDateTime>
- 5#include <QDebug>
- 6#include <QPainter>
- 7#include <QDateTime>
- 8#include "ctestreport.h"
- 9
- 10CTestReport::CTestReport(QObject *parent)
- 11{
- 12 m_startx = 30;
- 13 m_starty = 30;
- 14 m_width = 720; //试出来的尺寸像素点
- 15 m_height = 1035;
- 16
- 17 m_titleHeight = 35;
- 18
- 19 m_colNum = 10; //初始化
- 20 m_rowNum = 40; //计算表格的行数
- 21 m_colWidth = m_width / m_colNum;
- 22 m_rowHeight= m_height / m_rowNum;
- 23
- 24}
- 25
- 26CTestReport::~CTestReport()
- 27{
- 28
- 29}
- 30
- 31void CTestReport::printWithPreview()
- 32{
- 33 QPrinter printer(QPrinter::ScreenResolution);
- 34 printer.setPageSize(QPrinter::A4);
- 35 printer.setOrientation(QPrinter::Portrait); //打印方向 Portrait 纵向,Landscape:横向
- 36// printer.setOutputFormat(QPrinter::NativeFormat);
- 37 QPrintPreviewDialog preview(&printer);
- 38 connect(&preview, SIGNAL(paintRequested(QPrinter*)), this, SLOT(printDocument(QPrinter*)));
- 39 preview.setWindowState(Qt::WindowMaximized);
- 40 preview.exec();
- 41}
- 42
- 43void CTestReport::printDirect()
- 44{
- 45 QPrinter printer(QPrinter::ScreenResolution);
- 46 printer.setPageSize(QPrinter::A4);
- 47 QPrintDialog printDialog(&printer);
- 48 printer.setOrientation(QPrinter::Portrait); //打印方向
- 49
- 50 if (printDialog.exec() == QDialog::Accepted)
- 51 {
- 52 printDocument(&printer);
- 53 }
- 54}
- 55
- 56
- 57void CTestReport::drawTable(QPainter *painter, int no)
- 58{
- 59 //调整表格整体的高度
- 60
- 61 //总框体
- 62 painter->drawRect(m_startx,m_starty,m_width,m_height);
- 63 //标题栏
- 64 painter->drawLine(m_startx,m_starty+m_titleHeight,m_startx+m_width,m_starty+m_titleHeight);
- 65 painter->setFont(QFont("宋体", 20));
- 66 painter->drawText(QRect(m_startx,m_starty+3,m_width,m_titleHeight), Qt::AlignCenter, QString("测试报表%1").arg(no));
- 67 painter->drawLine(m_startx,m_starty+m_height,m_startx+m_width,m_starty+m_height);
- 68
- 69
- 70 int x1,y1,x2,y2;
- 71
- 72 painter->setFont(QFont("宋体", 10));
- 73 //绘制表格列单元线
- 74 for (int i = 1; i < m_colNum; i++)
- 75 {
- 76 x1 = m_startx + m_colWidth*i;
- 77 y1 = m_startx + m_titleHeight;
- 78 x2 = m_startx + m_colWidth*i;
- 79 y2 = m_starty + m_height;
- 80 painter->drawLine(x1, y1, x2, y2);
- 81
- 82 painter->drawText(QRectF(x1,y1,m_colWidth,m_rowHeight), Qt::AlignCenter, QString("%1列").arg(i));
- 83 }
- 84
- 85
- 86 //第一行为序号
- 87 for (int rowNo = 1; rowNo <= m_rowNum; rowNo++)
- 88 {
- 89 x1 = m_startx;
- 90 y1 = m_starty+m_titleHeight + m_rowHeight*rowNo;
- 91 x2 = m_startx + m_width;
- 92 y2 = m_starty+m_titleHeight + m_rowHeight*rowNo;
- 93
- 94 //标题
- 95 if (rowNo > 1)
- 96 painter->drawText(QRect(x1,y1-m_rowHeight, m_colWidth,m_rowHeight), Qt::AlignCenter, QString("%1").arg(rowNo-1));
- 97
- 98
- 99 //行线
- 100 if ( rowNo == m_rowNum) //最后一行不划线
- 101 {
- 102 break;
- 103 }
- 104
- 105 painter->drawLine(x1, y1, x2, y2);
- 106 }
- 107
- 108 //表最下面的备注
- 109 painter->drawText(QRect(m_startx,m_starty+m_height+2,450,25), Qt::AlignLeft, "注:测试报表备注信息。");
- 110
- 111 //制表时间 2020-12-28
- 112 QString dateTime = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
- 113 painter->drawText(QRect(m_startx+m_width-200,m_starty+m_height+2,200,m_rowHeight), Qt::AlignRight, "制表时间:"+dateTime);
- 114
- 115}
- 116
- 117void CTestReport::printDocument(QPrinter *printer)
- 118{
- 119 QPainter painter;
- 120
- 121 painter.begin(printer);
- 122
- 123 painter.setPen(Qt::black);
- 124
- 125 for (int i = 0; i < 5; i++)
- 126 {
- 127 printOnePage(&painter,i+1);
- 128
- 129 if ( i != 4 ) //判断是否最后一页,如果不是最后一页则新建一页
- 130 {
- 131 printer->newPage(); //新建页
- 132 painter.setPen(Qt::black);
- 133 }
- 134 }
- 135
- 136 painter.end();
- 137}
- 138
- 139void CTestReport::printOnePage(QPainter *painter, int no)
- 140{
- 141// qDebug()<<"reportInfo title: "<<reportInfo->getTitle();
- 142
- 143 //正常使用painter 绘制文字、pixmap等在printer上
- 144
- 145 drawTable(painter,no);
- 146
- 147
- 148}
测试调用代码,我是放到一个按键的槽函数里调用的:
- 1void MainWindow::on_btnReport_clicked()
- 2{
- 3 CTestReport reporter;
- 4
- 5 reporter.printWithPreview();
- 6
- 7}
效果

效果