PDA

View Full Version : QTableView printing(Qt Commercial Support Weekly #25 – Printing large tables)



creatron
1st November 2015, 11:17
I am trying to use the code snippets as in
https://translate.googleusercontent.com/translate_c?depth=1&hl=en&prev=search&rurl=translate.googleusercontent.com&sl=fr&u=https://blog.qt.io/blog/2012/08/24/qt-commercial-support-weekly-25-printing-large-tables-2/&usg=ALkJrhhsnsKpYY6iZ7ievW1SwcjvG1gKiA

Unfornunatly the example link http://83.145.193.200/Global/Images/Qt/Files/printTable-support_weekly_25_.zip is invalid.



Have you ever had problems printing a large table? Every now and then is approached with media issues is how to accomplish achieve this. The problem comes When one: has a QTableView and it's larger than what is shown on the screen. Using grabWidget () method is the general way to go about this, how do we aim wears it so que la pixmap created can be used for printing?


This is exactly what I want to do, print a spreadsheet, but could not get the code functional.

I tried to make this working with the following class, and just instantiate from the ui where I want to print the tableView:



#ifndef TABLE_PRIINTER_H
#define TABLE_PRIINTER_H

#include <QMainWindow>
#include <QObject>
#include "QTableWidget"
#include <QPrinter>
#include <QPrintDialog>

class table_printer : public QMainWindow
{
Q_OBJECT
public:
explicit table_printer(QWidget *parent = 0);

void print_table (QTableWidget *tableWidget);
signals:

public slots:
};




#include "table_printer.h"
#include <QHeaderView>
#include <qpainter.h>

table_printer::table_printer(QWidget *parent) : QMainWindow(parent)
{

}
/** ---------------------------------------------------------------------------
* @brief table_printer::print_table
* @param tableWidget
*/
void table_printer::print_table (QTableWidget * tableWidget)
{
//QPrinter * printer = new QPrinter;
QPrinter * printer = new QPrinter(QPrinter::HighResolution);

QPrintDialog printer_dialog(printer);

printer->setOutputFileName("altium_bom.pdf");
if (printer_dialog.exec() == QDialog::Accepted)
{
printer->setPaperSize(QPrinter::A3);
printer->setFullPage(true);
printer->setOrientation(QPrinter::Landscape);
QPainter painter(printer);

const int rows = tableWidget->model()->rowCount();
const int columns = tableWidget->model()->columnCount();
double totalWidth = tableWidget->verticalHeader()->width();

for (int c = 0; c < columns; ++c)
totalWidth += tableWidget->columnWidth(c);

double totalHeight = tableWidget->horizontalHeader()->height();

for (int r = 0; r < rows; ++r)
totalHeight += tableWidget->rowHeight(r);

// To avoid possible visual updates we will use a temporary
// QTableView which is not shown on the screen which we can
// ensure with the WA_DontShowOnScreen attribute.
// We will set the size of the table based on the width and
// height we just calculated. Also we will make sure that scrollbars
// are not shown for the table.
// Then we can use the grabWidget() method to paint the table.


QTableView tempTable;
tempTable.setAttribute(Qt::WA_DontShowOnScreen);
tempTable.setModel(tableWidget->model());
tempTable.setFixedSize(totalWidth, totalHeight);
tempTable.setVerticalScrollBarPolicy(Qt::ScrollBar AlwaysOff);
tempTable.setHorizontalScrollBarPolicy(Qt::ScrollB arAlwaysOff);
QPixmap grabPixmap = QPixmap::grabWidget(&tempTable);


// Now we have our table widget with all the items and headers painted to a pixmap.
// If we try to print this pixmap, then what will most likely happen is that the
// columns or the rows are not evenly divided between pages.
// Some of them may be cut in half. This makes reading the printed table very
// difficult. We have to print the table so that only full rows and
// columns are printed to each page.

// What we will do to help resolve this is to use a helper rectangle to
// define the area from the pixmap that is printed into one page.
// To make this example straightforward to read we will define the
// amount of columns and rows printed.
// This can easily be changed so that the width and height is compared
// to the actual page size.

// First we will take the first four rows and columns (along with the headers)
// and calculate the space they occupy.
// The helper rectangle is used for this. Then we will use this rectangle
// to take the correct part of the grabbed pixmap for printing.
// Needed variables are initialized and then the size of the rectangle
// is added up.

// The fact that the horizontal header is only printed with the top most items
// and the vertical header with the left most items is taken into account.


QRectF sourceRect;
double totalPageHeight = tableWidget->horizontalHeader()->height();
int columnCount = 0;
int rowCount = 0;

// First take the rows that fit into one page
for (int h = 0; h < tableWidget->model()->rowCount(); h++)
{
totalPageHeight += tableWidget->rowHeight(h);
double totalPageWidth = tableWidget->verticalHeader()->width();

// When we have reached the amount of rows we will print into one page,
// the width of the columns we want into that page is defined.

if (rowCount == 3 || h == tableWidget->model()->rowCount() - 1)
{
// Then take the columns that fit into one page
for (int w = 0; w < tableWidget->model()->columnCount(); w++)
{
totalPageWidth += tableWidget->columnWidth(w);

// Now that we have determined the size of the rows and
// columns, the size is set to the rectangle we use for printing.
// Now the first part of the table is ready for printing.

if ( (columnCount == 3) ||
(w == tableWidget->model()->columnCount() - 1))
{
sourceRect.setWidth(totalPageWidth);
sourceRect.setHeight(totalPageHeight);
painter.drawPixmap(printer->pageRect().topLeft(),
grabPixmap, // pixmap,
sourceRect);
// After printing the first page we have to adjust the
// rectangle so that it’s moved to the next part of the
// table we want to print. To be able to print the next
// area to a new page, a page break is added and the page
// width and column count are reset.
// This way we can continue on to the next page and start
// going through the columns from the beginning.

sourceRect.setLeft(sourceRect.left() + totalPageWidth);
if (w != tableWidget->model()->columnCount() - 1)
printer->newPage();
totalPageWidth = 0;
columnCount = 0;

// A page break is also needed after all the rows in one page
// have been counted in. As with the rows, the rectangle is
// adjusted to the next part of the table and the page
// height is reset. We will cover all the parts of the
// pixmap this way until the whole table is printed out.

sourceRect.setTop(sourceRect.top() + totalPageHeight);
sourceRect.setLeft(0);
if (h != tableWidget->model()->rowCount() - 1)
printer->newPage();
totalPageHeight = 0;
rowCount = 0;
}
}
}
}
tableWidget->render(&painter);
}
}

This works but I get two images, either very very small (double image), or if I remove 'hi-resolution' only the first page with another one at the back of it, as one would get with a normal print-screen. I attach a sample of low and high resolution 'printouts'.

Normal print-screen was done with


QPrintDialog printer_dialog(printer);

if (printer_dialog.exec() == QDialog::Accepted)
{
printer->setPaperSize(QPrinter::A3);
printer->setFullPage(true);
printer->setOrientation(QPrinter::Landscape);

QPainter painter(printer);
ui.tw_price_list->render(&painter);
}

This could be very use full class if one could fix this.

Any Ideas?

Thanks