Qt报表实现-QPainter + QPrinter
QPainter是可以在QPrinter上绘制图形和文字的,利用这个方法,可以绘制任何图形或者文字、表格等,可以实现复杂的表格绘制,如果报表比较特殊,可以尝试使用这个方法,下面简单介绍一下实现的过程。
报表绘制
实现简介
我这边里封装了一个报表打印类,用于打印报表,当前并没有传入数据和参数,实际实际项目是需要传入参数和数据的。
首先是打印的接口代码:
void printWithPreview(); void printDirect(); void printOnePage(QPainter *painter, int no);
printWithPreview 是用于调出打印预览窗口;
printDirect 是直接打印
printOnePage 是打印一页;因为可能会打印多个页,所以这里把一页的绘制单独封装为一个函数
打印信号处理槽函数,用于接收打印信号,在这个函数里调用printOnePage去绘制要打印的报表。
void printDocument(QPrinter *printer);
打印版式设置
横向打印和纵向打印;
打印方向 Portrait 纵向,Landscape:横向
使用如下函数设置
enum Orientation { Portrait, Landscape }; void setOrientation(Orientation);
代码
头文件:
#ifndef CTESTREPORT_H #define CTESTREPORT_H #include <QObject> #include <QAbstractItemModel> #include <QPrinter> #include <QVariantMap> #include <QVariantList> class CTestReport:public QObject { Q_OBJECT public: explicit CTestReport(QObject *parent = nullptr); virtual ~CTestReport(); void printWithPreview(); void printDirect(); void printOnePage(QPainter *painter, int no); private: void drawTable(QPainter *painter, int no); signals: public slots: private slots: void printDocument(QPrinter *printer); private: int m_startx; //整体表格在A4纸中的起始x坐标 int m_starty; //整体表格在A4纸中的起始y坐标 int m_width; //整体表格的宽 int m_height; //整体表格的高 int m_titleHeight; //标题栏的高 int m_colNum ; //表格的总列数 int m_rowNum ; //表格的总行数 int m_rowHeight; //单元表格高 int m_colWidth; //单元表格宽 }; #endif // CTESTREPORT_H
类实现源文件:
#include <QPrintPreviewDialog> #include <QPrintDialog> #include <QPrinter> #include <QDateTime> #include <QDebug> #include <QPainter> #include <QDateTime> #include "ctestreport.h" CTestReport::CTestReport(QObject *parent) { m_startx = 30; m_starty = 30; m_width = 720; //试出来的尺寸像素点 m_height = 1035; m_titleHeight = 35; m_colNum = 10; //初始化 m_rowNum = 40; //计算表格的行数 m_colWidth = m_width / m_colNum; m_rowHeight= m_height / m_rowNum; } CTestReport::~CTestReport() { } void CTestReport::printWithPreview() { QPrinter printer(QPrinter::ScreenResolution); printer.setPageSize(QPrinter::A4); printer.setOrientation(QPrinter::Portrait); //打印方向 Portrait 纵向,Landscape:横向 // printer.setOutputFormat(QPrinter::NativeFormat); QPrintPreviewDialog preview(&printer); connect(&preview, SIGNAL(paintRequested(QPrinter*)), this, SLOT(printDocument(QPrinter*))); preview.setWindowState(Qt::WindowMaximized); preview.exec(); } void CTestReport::printDirect() { QPrinter printer(QPrinter::ScreenResolution); printer.setPageSize(QPrinter::A4); QPrintDialog printDialog(&printer); printer.setOrientation(QPrinter::Portrait); //打印方向 if (printDialog.exec() == QDialog::Accepted) { printDocument(&printer); } } void CTestReport::drawTable(QPainter *painter, int no) { //调整表格整体的高度 //总框体 painter->drawRect(m_startx,m_starty,m_width,m_height); //标题栏 painter->drawLine(m_startx,m_starty+m_titleHeight,m_startx+m_width,m_starty+m_titleHeight); painter->setFont(QFont("宋体", 20)); painter->drawText(QRect(m_startx,m_starty+3,m_width,m_titleHeight), Qt::AlignCenter, QString("测试报表%1").arg(no)); painter->drawLine(m_startx,m_starty+m_height,m_startx+m_width,m_starty+m_height); int x1,y1,x2,y2; painter->setFont(QFont("宋体", 10)); //绘制表格列单元线 for (int i = 1; i < m_colNum; i++) { x1 = m_startx + m_colWidth*i; y1 = m_startx + m_titleHeight; x2 = m_startx + m_colWidth*i; y2 = m_starty + m_height; painter->drawLine(x1, y1, x2, y2); painter->drawText(QRectF(x1,y1,m_colWidth,m_rowHeight), Qt::AlignCenter, QString("%1列").arg(i)); } //第一行为序号 for (int rowNo = 1; rowNo <= m_rowNum; rowNo++) { x1 = m_startx; y1 = m_starty+m_titleHeight + m_rowHeight*rowNo; x2 = m_startx + m_width; y2 = m_starty+m_titleHeight + m_rowHeight*rowNo; //标题 if (rowNo > 1) painter->drawText(QRect(x1,y1-m_rowHeight, m_colWidth,m_rowHeight), Qt::AlignCenter, QString("%1").arg(rowNo-1)); //行线 if ( rowNo == m_rowNum) //最后一行不划线 { break; } painter->drawLine(x1, y1, x2, y2); } //表最下面的备注 painter->drawText(QRect(m_startx,m_starty+m_height+2,450,25), Qt::AlignLeft, "注:测试报表备注信息。"); //制表时间 2020-12-28 QString dateTime = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"); painter->drawText(QRect(m_startx+m_width-200,m_starty+m_height+2,200,m_rowHeight), Qt::AlignRight, "制表时间:"+dateTime); } void CTestReport::printDocument(QPrinter *printer) { QPainter painter; painter.begin(printer); painter.setPen(Qt::black); for (int i = 0; i < 5; i++) { printOnePage(&painter,i+1); if ( i != 4 ) //判断是否最后一页,如果不是最后一页则新建一页 { printer->newPage(); //新建页 painter.setPen(Qt::black); } } painter.end(); } void CTestReport::printOnePage(QPainter *painter, int no) { // qDebug()<<"reportInfo title: "<<reportInfo->getTitle(); //正常使用painter 绘制文字、pixmap等在printer上 drawTable(painter,no); }
测试调用代码,我是放到一个按键的槽函数里调用的:
void MainWindow::on_btnReport_clicked() { CTestReport reporter; reporter.printWithPreview(); }
效果
如下图,一共是5页: