Qt 報(bào)表實(shí)現(xiàn) -QPainter + QPrinter
QPainter 是可以在 QPrinter 上繪制圖形和文字的,利用這個(gè)方法,可以繪制任何圖形或者文字、表格等,可以實(shí)現(xiàn)復(fù)雜的表格繪制,如果報(bào)表比較特殊,可以嘗試使用這個(gè)方法,下面簡(jiǎn)單介紹一下實(shí)現(xiàn)的過(guò)程。
報(bào)表繪制
實(shí)現(xiàn)簡(jiǎn)介
我這邊里封裝了一個(gè)報(bào)表打印類(lèi),用于打印報(bào)表,當(dāng)前并沒(méi)有傳入數(shù)據(jù)和參數(shù),實(shí)際實(shí)際項(xiàng)目是需要傳入?yún)?shù)和數(shù)據(jù)的。
首先是打印的接口代碼:
1 void printWithPreview();
2 void printDirect();
3 void printOnePage(QPainter *painter, int no);
printWithPreview 是用于調(diào)出打印預(yù)覽窗口;
printDirect 是直接打印
printOnePage 是打印一頁(yè);因?yàn)榭赡軙?huì)打印多個(gè)頁(yè),所以這里把一頁(yè)的繪制單獨(dú)封裝為一個(gè)函數(shù)
打印信號(hào)處理槽函數(shù),用于接收打印信號(hào),在這個(gè)函數(shù)里調(diào)用 printOnePage 去繪制要打印的報(bào)表。
1 void printDocument(QPrinter *printer);
打印版式設(shè)置
橫向打印和縱向打??;
打印方向 Portrait 縱向,Landscape:橫向
使用如下函數(shù)設(shè)置
1enum Orientation { Portrait, Landscape };
2void setOrientation(Orientation);
代碼
頭文件:
1#ifndef CTESTREPORT_H
2#define CTESTREPORT_H
3
4#include
5#include
6#include
7#include
8#include
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 坐標(biāo)
35 int m_starty; // 整體表格在 A4 紙中的起始 y 坐標(biāo)
36 int m_width; // 整體表格的寬
37 int m_height; // 整體表格的高
38
39 int m_titleHeight; // 標(biāo)題欄的高
40
41 int m_colNum ; // 表格的總列數(shù)
42 int m_rowNum ; // 表格的總行數(shù)
43 int m_rowHeight; // 單元表格高
44 int m_colWidth; // 單元表格寬
45
46};
47
48
49#endif // CTESTREPORT_H
類(lèi)實(shí)現(xiàn)源文件:
1#include
2#include
3#include
4#include
5#include
6#include
7#include
8#include "ctestreport.h"
9
10CTestReport::CTestReport(QObject *parent)
11{
12 m_startx = 30;
13 m_starty = 30;
14 m_width = 720; // 試出來(lái)的尺寸像素點(diǎn)
15 m_height = 1035;
16
17 m_titleHeight = 35;
18
19 m_colNum = 10; // 初始化
20 m_rowNum = 40; // 計(jì)算表格的行數(shù)
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 // 調(diào)整表格整體的高度
60
61 // 總框體
62 painter->drawRect(m_startx,m_starty,m_width,m_height);
63 // 標(biāo)題欄
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("測(cè)試報(bào)表%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 // 第一行為序號(hào)
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 // 標(biāo)題
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, "注:測(cè)試報(bào)表備注信息。");
110
111 // 制表時(shí)間 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, "制表時(shí)間:"+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 ) // 判斷是否最后一頁(yè),如果不是最后一頁(yè)則新建一頁(yè)
130 {
131 printer->newPage(); // 新建頁(yè)
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: "<getTitle();
142
143 // 正常使用 painter 繪制文字、pixmap 等在 printer 上
144
145 drawTable(painter,no);
146
147
148}
測(cè)試調(diào)用代碼,我是放到一個(gè)按鍵的槽函數(shù)里調(diào)用的:
1void MainWindow::on_btnReport_clicked()
2{
3 CTestReport reporter;
4
5 reporter.printWithPreview();
6
7}
效果
效果