Qt报表实现-QPainter+QPrinter

目的

Qt报表本身已经封装的挺好了,熟悉几个函数就可以了,利用QPainter+QPrinter,可以实现像素级的控制,非常的灵活。
难度就在如何控制位置,用Excel这种类似的东西习惯了,用这个的确有些不适应,但细想一下,也没什么。
就是开始位置、行高、列宽、高度、宽度、行的数量、列的数量。
有了这些自己就可以画表格了。
参考网址:
https://blog.51cto.com/wuquan1230/4760333

情况

首先是打印的接口代码:
void printWithPreview();
void printDirect();
void printOnePage(QPainter *painter, int no);
printWithPreview 是用于调出打印预览窗口;
printDirect 是直接打印
printOnePage 是打印一页;因为可能会打印多个页,所以这里把一页的绘制单独封装为一个函数
打印信号处理槽函数,用于接收打印信号,在这个函数里调用printOnePage去绘制要打印的报表。

就拿细说一下打印预览,其它也其它相同,最终调用的核心处理过程,都是一样的:

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

这里面,作了打印预览的基本设置,这里出现了重要的对象就是:QPrinter,QT封装了打印的东西在里面,直接用它就好了,非常方便。
关键的函数实现在printDocument(QPrinter*)

void CTestReport::printDocument(QPrinter *printer)
{
    qDebug("enter function CTestReport::printDocument");
    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);
        }
    }
    //printOnePage(&painter,1);
    painter.end();
    qDebug("exit function CTestReport::printDocument");
}

最最关键的函数是这里:

void CTestReport::drawTable(QPainter *painter, int no)
{
    //m_titleHeight = m_titleHeight - 5;
    painter->setRenderHint(QPainter::Antialiasing, true);
    //调整表格整体的高度
    //总框体
    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->setFont(QFont("宋体", 10));
    painter->drawText(QRect(m_startx,m_starty,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_starty + m_titleHeight;
        x2 = m_startx + m_colWidth*i;
        y2 = m_starty + m_height;
        painter->drawLine(x1, y1, x2, y2);
        painter->drawText(QRectF(x1,y1+3,m_colWidth,m_rowHeight), Qt::AlignCenter|Qt::AlignHCenter, 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);
}

这里,真正实现了画了表格与数据,一切都是画出来的。
最终效果如下:
在这里插入图片描述

总结

这里最关键就是根据位置进行画了,有些复杂,但可以精确控制位置,也是非常好的。
其坐标在左上角,这与视图的坐标是一致的,其实,可以理解,其就是这么一个图:
在这里插入图片描述

然后,就可以按照这种坐标,进行画自己想要的东西:表格、文字、图画等。
项目下载地址:https://download.csdn.net/download/maokexu123/89478200

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员如山石

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值