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();
}
效果