通过Qt开发电子报表软件,在打印问题上遇到难题,参考网上的方法,很少,几乎没有相关的解决方法!只有自力更生了,结合QT自带实例spreadsheet, 打印只能实现当前页的打印,并不能实现分页,分区域打印。
void PrintView::print(QPrinter *printer)
{
#ifndef QT_NO_PRINTER
resize(printer->width(), printer->height());
render(printer);
}
例子上的函数如上, 看到render函数,是把当前tableview内容绘制到打印机上。灵感即来于此!整体思路是把tableview根据打印机尺寸划分打印区域,把打印区域分块绘制到打印机上,每个区域作为一页。
具体看代码:
1. 计算行页数,及每页起始行号及区域高度
void PrintView::CalcultPrintAreaRow(int h, int &pageCount, QVector<int> &printAreaStartRow, QVector<int> &printAreaHeight)
{
int pix_height = 0;
QAbstractItemModel *item_model = this->model();
if (item_model == NULL) return;
QHeaderView *headerView = this->horizontalHeader ();
if (headerView != NULL) pix_height = headerView->height();
pageCount = 0;
int i;
printAreaStartRow.push_back(0);
for (i = 0; i < item_model->rowCount(); ) {
if ((pix_height + rowHeight(i)) > h) {
printAreaStartRow.push_back(i);
printAreaHeight.push_back(pix_height);
pix_height = headerView->height();
pageCount ++;
continue;
}
pix_height += rowHeight(i);
i++;
}
if (pix_height <= h) {
printAreaStartRow.push_back(i);
printAreaHeight.push_back(pix_height);
pageCount ++;
}
}
2.计算列页数及每页起始列号及打印区域宽度
void PrintView::CalcultPrintAreaCol(int w, int &pageCount, QVector<int> &printAreaStartCol, QVector<int> &printAreaWidth)
{
int pix_width = 0;
QAbstractItemModel *item_model = this->model();
if (item_model == NULL) return;
QHeaderView *headerView = this->verticalHeader ();
if (headerView != NULL) pix_width = headerView->width();
pageCount = 0;
int i;
printAreaStartCol.push_back(0);
for (i = 0; i < item_model->columnCount(); ) {
if ((pix_width + columnWidth(i)) > w) {
printAreaStartCol.push_back(i);
printAreaWidth.push_back(pix_width);
pix_width = headerView->width();
pageCount ++;
continue;
}
pix_width += columnWidth(i);
i++;
}
if (pix_width <= w) {
printAreaStartCol.push_back(i);
printAreaWidth.push_back(pix_width);
pageCount ++;
}
}
3.计算整个页面宽度
int PrintView::CalcultTableViewWidth()
{
int pix_width = 0;
QAbstractItemModel *item_model = this->model();
if (item_model == NULL) return 0;
QHeaderView *headerView = this->verticalHeader ();
if (headerView != NULL) pix_width = headerView->width();
for (int i = 0; i < item_model->columnCount(); i++) {
pix_width += columnWidth(i);
}
return pix_width;
}
4.计算整个页面高度
int PrintView::CalcultTableViewHeight()
{
int pix_height = 0;
QAbstractItemModel *item_model = this->model();
if (item_model == NULL) return 0;
QHeaderView *headerView = this->horizontalHeader ();
if (headerView != NULL) pix_height = headerView->height();
for (int i = 0; i < item_model->rowCount(); i++) {
pix_height += rowHeight(i);
}
return pix_height;
}
void PrintView::print(QPrinter *printer)
{
#ifndef QT_NO_PRINTER
resize(printer->width(), printer->height());
int marginLeft = 20, marginTop = 20, marginRight = 20, marginBottom = 20;
QRect paperRect = printer->paperRect();
paperRect.adjust(0, 0, - marginLeft - marginRight, - marginTop - marginBottom);
int i,j,k;
int row_pageCount = 1, col_pageCount = 1;
QVector<int> printAreaStartRow, printAreaHeight;
QVector<int> printAreaStartCol, printAreaWidth;
CalcultPrintAreaRow(paperRect.height(), row_pageCount, printAreaStartRow, printAreaHeight);
CalcultPrintAreaCol(paperRect.width(), col_pageCount, printAreaStartCol, printAreaWidth);
//限制打印页数, 处理实际打印页(根据需要自己处理,判断有效打印区域)
CalcultTableViewPage(printAreaStartRow, printAreaStartCol, row_pageCount, col_pageCount);
QPainter painter(printer);
painter.begin(printer);
//隐藏行列很重要,慢慢体会吧
for (i = 0; i < row_pageCount; i ++) {
for (k = 0; k < this->model()->columnCount(); k++) setColumnHidden(k, false); //重新把列显示出来
for (j = 0; j < col_pageCount; j++) {
resize(printAreaWidth[j], printAreaHeight[i]);
render(&painter, QPoint(marginLeft, marginTop), QRegion(0, 0, printAreaWidth[j], printAreaHeight[i]), QWidget::DrawChildren); //绘制到指定区域
//隐藏列
for (k = printAreaStartCol[j]; k < printAreaStartCol[j + 1]; k++) setColumnHidden(k, true);
if (i != (row_pageCount - 1) ||
j != (col_pageCount - 1)) printer->newPage(); //创建新页
}
//隐藏行
for (k = printAreaStartRow[i]; k < printAreaStartRow[i + 1]; k++) setRowHidden(k, true);
}
painter.end();
#endif
}