Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

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:

    1. Using QTextDocument.
    2. Using QTextCursor::insertTable().
    3. Populating the cells from the underlying QAbstractItemModel's data.
    4. Using QTextDocument::toHtml() to get an HTML <TABLE> representation.
    5. 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.
    

Log in to reply