Python Forum
Printing QTableWidget to an DIN A4 page
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Printing QTableWidget to an DIN A4 page
#1
How can I layout the printout to an pdf/page of a QTableWidget ?
This is what i want to do (even for just a single tip for one of them i am a million times thankfull):
- set the width of the Table
- set the color of the headers of the Table
- set the startingpoint of the Table printout to the middle of the page ?
- set an picture on the lopright of the page
- inserted an horizontal line somewhere in the page

I created a destopapp with and QTableWidget in it. I am using QtPrintSupport to print it/make an pdf of it.
Right now i am only able to inseart the table and a picture but i am not able to set the size of them and the location. Help will be much appreciated.
I am using python 3.6 and pyqt5.

Here is my code so far (in shorted to only show relevent stuff)

from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from itertools import cycle
from PyQt5 import QtCore, QtGui, QtWidgets, QtPrintSupport
from pandas import DataFrame
import sys
import xlsxwriter
import datetime

found_words_all = int('100')
l_words_all = ['a', 'b']
data_all = {'hi': ['ab hi', 'bald'], 'hi2': ['d', 'c']}


textMargins = 12
borderMargins = 10


class main_result_all(QtWidgets.QWidget):
    def __init__(self, parent=None, data=None):
        super(main_result_all, self).__init__(parent)

        self.buttonPreview = QtWidgets.QPushButton('Druckvorschau', self)
        self.buttonPreview.setGeometry(QtCore.QRect(555, 700, 250, 30))
        self.buttonPreview.clicked.connect(self.handlePreview)

        self.table = QTableWidget(self)
        self.table.setGeometry(QtCore.QRect(15, 10, 1015, 610))
        self.table.setRowCount(found_words_all)
        self.table.setColumnCount(6)
        stylesheet = "::section{Background-color:rgb(137,137,140);border-radius:14px;font: bold}"
        self.table.horizontalHeader().setStyleSheet(stylesheet)
        self.table.verticalHeader().setSectionResizeMode(QtWidgets.QHeaderView.ResizeToContents)
        self.table.setSortingEnabled(True)

        horHeaders = []
        for col, key in enumerate(sorted(data_all.keys())):
            horHeaders.append(key)
            for row, item in enumerate(data_all[key]):
                clean_item = item
                if type(item) == tuple:
                    clean_item = item[0]
                newitem = QTableWidgetItem(clean_item)
                self.table.setItem(row, col, newitem)

    def handlePreview(self, printer):
        dialog = QtPrintSupport.QPrintPreviewDialog()
        dialog.paintRequested.connect(self.printDocument)
        dialog.exec_()
        '''
        fn, _ = QFileDialog.getSaveFileName(self, 'Speichern unter', None, 'Pdf Dateien (.pdf);;Alle Dateien()')
        if fn != '':
            if QFileInfo(fn).suffix() == "": fn += '.pdf'

            printer = QPrinter(QPrinter.HighResolution)
            printer.setPageSize(QPrinter.A4)
            printer.setOutputFormat(QPrinter.PdfFormat)
            printer.setOutputFileName(fn)
            self.printDocument.document().print_(printer)
        '''

    def mmToPixels(self, printer, mm):
        return mm * 0.039370147 * printer.resolution()

    def paintPage(self, pageNumber, pageCount, painter, doc, textRect, footerHeight):
        painter.save()
        textPageRect = QtCore.QRectF(QtCore.QPointF(0, pageNumber * doc.pageSize().height()), doc.pageSize())
        painter.setClipRect(textRect)
        painter.translate(0, -textPageRect.top())
        painter.translate(textRect.left(), textRect.top())
        doc.drawContents(painter)
        painter.restore()
        footerRect = QtCore.QRectF(textRect)
        footerRect.setTop(textRect.bottom())
        footerRect.setHeight(footerHeight)

        headerRect = QtCore.QRectF(textRect)
        headerRect.setTop(textRect.top())
        headerRect.setHeight(2 * footerHeight)

        # draw footer
        painter.save()
        pen = painter.pen()
        pen.setColor(QtCore.Qt.black)
        painter.setPen(pen)
        painter.drawText(footerRect, QtCore.Qt.AlignCenter, "Seite {} von {}".format(pageNumber + 1, pageCount))
        painter.drawText(headerRect, QtCore.Qt.AlignLeft, "{}\n{}".format('Projektname:', 'Projektnummer:'))
        #  painter.drawImage(40,40,"Bild-Programm.png")
        #################################
        #  painter.drawPicture(headerRect, QtCore.Qt.AlignRight, "beispiel_bild.png")
        #  painter.drawLine(headerRect, QtCore.Qt.AlignCenter)

        painter.restore()

    def printDocument(self, printer):

        painter = QtGui.QPainter(printer)
        document = QtGui.QTextDocument()
        cursor = QtGui.QTextCursor(document)
        blockFormat = QtGui.QTextBlockFormat()  #
        cursor.insertImage("Bild-Programm.png")
        # cursor.setPositon

        cursor.insertBlock(blockFormat)
        blockFormat.setPageBreakPolicy(QtGui.QTextFormat.PageBreak_AlwaysBefore)

        table = cursor.insertTable(self.table.rowCount(), self.table.columnCount())

        for row in range(table.rows()):
            for col in range(table.columns()):
                it = self.table.item(row, col)
                if it is not None:
                    cursor.insertText(it.text())
                cursor.movePosition(QtGui.QTextCursor.NextCell)

        document.print_(printer)

        doc = document

        doc.documentLayout().setPaintDevice(printer)
        doc.setPageSize(QtCore.QSizeF(printer.pageRect().size()))
        pageSize = printer.pageRect().size()
        tm = self.mmToPixels(printer, textMargins)
        footerHeight = painter.fontMetrics().height()
        textRect = QtCore.QRectF(tm, tm, pageSize.width() - 2 * tm, pageSize.height() - 2 * tm - footerHeight)
        doc.setPageSize(textRect.size())
        pageCount = doc.pageCount()

        for pageIndex in range(pageCount):
            if pageIndex != 0:
                printer.newPage()
            self.paintPage(pageIndex, pageCount, painter, doc, textRect, footerHeight)

def main():
    app = QApplication(sys.argv)
    ex = main_result_all()
    ex.show()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()
Reply
#2
for the color of the header your code is correct.
I only change this line
stylesheet = "::section{Background-color:rgb(190,1,1);border-radius:14px}"
to
stylesheet = "::section{Background-color:rgb(0, 0, 255);border-radius:14px;font: bold}"
.I will check later
Reply
#3
The Layout is not good, resizing the window should resize the Table too.
The PushButton is no longer visible when you zoom out of the window.

border-radius:14px does nothing here, value is too big

using this gives me rounded corners
stylesheet = "::section{background-color:blue;color: lightgray; border: 1px solid black; border-radius:10px;font: bold}"
Error Message on 'Druckvorschau'
Output:
QPainter::begin: A paint device can only be painted by one painter at a time.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  [PyQt] QTableWidget print problem JokerSob 8 4,685 Jan-28-2022, 06:08 PM
Last Post: Axel_Erfurt
  [PyQt] How do I display the DB table I will choose from the QComboBox in QTableWidget JokerSob 2 2,271 Aug-05-2021, 03:00 PM
Last Post: JokerSob
  Displaying database info in QTableWidget thewolf 6 5,181 Apr-03-2021, 02:49 PM
Last Post: thewolf
  [PyQt] Help: check content of combobox in horizontal header of QTableWidget mart79 1 3,267 Jul-26-2020, 06:18 PM
Last Post: deanhystad
  [PyQt] Add validation (regex) to QTableWidget cells mart79 0 2,689 May-05-2020, 12:51 PM
Last Post: mart79
  [PyQt] QTableWidget stylesheet error mart79 3 6,326 Feb-26-2020, 04:54 PM
Last Post: Denni
  [PyQt] Pyqt5: How do you make a button that adds new row with data to a Qtablewidget YoshikageKira 6 6,873 Jan-02-2020, 04:32 PM
Last Post: Denni
  [PyQt] QTableWidget cell validation littleGreenDude 1 7,611 Jan-18-2019, 07:44 PM
Last Post: littleGreenDude
  [PyQt]Find item or text in Qtablewidget maziio 0 11,210 Aug-06-2018, 01:37 PM
Last Post: maziio

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020