QPdfwiter/QPrinter
-
hi everyone,
is there any way to print the content of of a QAbstractItemView (QTableWidget for example) into a QPaintDevice (PDF file) using QPainter ans QPdfWriter ?
-
@Aitslimane
Now it's funny you should ask this, because I think it's the same question I was faced with just a few days ago!!I wanted to be able to export a
QTableView
to PDF, generically.First, I'll say I decided not to do it the "paint" way, for your consideration of an alternative!
I was already offering to export the data cells to CSV file (for Excel). I decided that I was not particularly caring of the table view's actual graphics. So instead I would go down the route of exporting "as data for a table".
I ended up:
- Using
QTextDocument
. - Using
QTextCursor::insertTable()
. - Populating the cells from the underlying
QAbstractItemModel
's data. - Using
QTextDocument::toHtml()
to get an HTML<TABLE>
representation. - Finally sending that off to one of my existing HTML-to-PDF functions (I use
QWebEnginePage::printfToPdf()
, but there are others).
I have been very happy with this approach, rather than actually trying to paint from the view. (It also scales nicely if you find you want to export to anything other than PDF, e.g. you can get a text-only representation.)
FWIW, I paste at the end some "extracts" of my code to give you a flavour and see if it suits you.
Now, if you really do want to go down the view-paint-PDF route, I can doubtless dig out the stackoverflow I came across to do it that way. However, IIRC, one issue was you had to implement your own scrolling to paint the "hidden" parts of the view to PDF, which was one reason I rejected that approach. Let me know if you still want that?
Some of my
QTextDocument
code:class JTextDocument(QTextDocument): @staticmethod def setTextCursorHAlign(cursor: QTextCursor, hAlign: Qt.AlignmentFlag): blockFormat = cursor.blockFormat() alignment = (blockFormat.alignment() & Qt.AlignVertical_Mask) | (hAlign & Qt.AlignHorizontal_Mask) blockFormat.setAlignment(alignment) cursor.setBlockFormat(blockFormat) def insertTableForModel(self, cursor: QTextCursor, model: QAbstractItemModel) -> QTextTable: sourceModel = model if isinstance(model, QAbstractProxyModel): sourceModel = model.sourceModel() rowCnt = model.rowCount() colCnt = model.columnCount() tableFormat = QTextTableFormat() table = cursor.insertTable(rowCnt + 1, colCnt, tableFormat) headerFont = QTextCharFormat() headerFont.setFontWeight(QFont.Bold) for col in range(colCnt): headerCell = table.cellAt(0, col) cursor = headerCell.firstCursorPosition() self.setTextCursorHAlign(cursor, Qt.AlignHCenter) item = sourceModel.horizontalHeaderItem(col) cursor.insertText(item.text(), headerFont) for row in range(rowCnt): for col in range(colCnt): cell = table.cellAt(row + 1, col) cursor = cell.firstCursorPosition() val = model.data(model.index(row, col), Qt.DisplayRole) alignment = model.data(model.index(row, col), Qt.TextAlignmentRole) if alignment is not None: self.setTextCursorHAlign(cursor, alignment) cursor.insertText(val) return table # Sample caller outline: doc = JTextDocument(self) font = QFont("Verdana", 10) doc.setDefaultFont(font) doc.setDocumentMargin(10) cursor = QTextCursor(doc) cursor.movePosition(QTextCursor.Start) table = doc.insertTableForModel(cursor, model) cursor.movePosition(QTextCursor.End) html = doc.toHtml() # Now that you have HTML, do whatever to export that to PDF etc.
- Using