Шаг 301.
Библиотека PyQt5.
Печать документов. Основные средства печати. Вывод на печать (окончание)

    На этом шаге мы приведем пример класса который можно использовать при выводе на печать.

    В тексте ниже приведен код класса PrintList, реализующий печать списков или содержимого таблиц баз данных в виде полноценного табличного отчета. Этот класс можно использовать для разработки приложений.

from PyQt5 import QtCore, QtGui, QtPrintSupport

class  PrintList:
    def __init__(self) :
        self.printer = QtPrintSupport.QPrinter()
        self.headerFont = QtGui.QFont("Arial", pointSize=10,
                    weight = QtGui.QFont.Bold)
        self.bodyFont = QtGui.QFont("Arial", pointSize=10)
        self.footerFont = QtGui.QFont("Arial", pointSize=9, italic=True)
        self.headerFlags = QtCore.Qt.AlignHCenter | QtCore.Qt.TextWordWrap
        self.bodyFlags = QtCore.Qt.TextWordWrap
        self.footerFlags = QtCore.Qt.AlignHCenter | QtCore.Qt.TextWordWrap
        color = QtGui.QColor(QtCore.Qt.black)
        self.headerPen = QtGui.QPen(color, 2)
        self.bodyPen = QtGui.QPen(color, 1)
        self.margin = 5
        self._resetData()

    def _resetData(self):
        self.headers = None
        self.columnWidths = None
        self.data = None
        self._brush = QtCore.Qt.NoBrush
        self._currentRowHeight = 0
        self._currentPageHeight = 0
        self._headerRowHeight = 0
        self._footerRowHeight = 0
        self._currentPageNumber = 1
        self._painter = None

    def printData(self):
        self._painter = QtGui.QPainter()
        self._painter.begin(self.printer)
        self._painter.setBrush(self._brush)
        if self._headerRowHeight == 0:
            self._painter.setFont(self.headerFont)
            self._headerRowHeight = 
                  self._calculateRowHeight(self.columnWidths, self.headers)
        if self._footerRowHeight == 0:
            self._painter.setFont(self.footerFont)
            self._footerRowHeight = 
                  self._calculateRowHeight([self.printer.width()], "Страница")
        for i in range(len(self.data)):
            height = self._calculateRowHeight(self.columnWidths, self.data[i])
            if self._currentPageHeight + height > 
                  self.printer.height() - self._footerRowHeight - 2 * self.margin:
                self._printFooterRow()
                self._currentPageHeight = 0
                self._currentPageNumber += 1
                self.printer.newPage()
            if self._currentPageHeight == 0:
                self._painter.setPen(self.headerPen)
                self._painter.setFont(self.headerFont)
                self.printRow(self.columnWidths, self.headers,
                        self._headerRowHeight, self.headerFlags)
                self._painter.setPen(self.bodyPen)
                self._painter.setFont(self.bodyFont)
            self.printRow(self.columnWidths, self.data[i],
                          height, self.bodyFlags)
        self._printFooterRow()
        self._painter.end()
        self._resetData()

    def _calculateRowHeight(self, widths, cellData):
        height = 0
        for i in range(len(widths)):
            r = self._painter.boundingRect(0, 0, widths[i] -
                    2 * self.margin, 50, QtCore.Qt.TextWordWrap,
                    str(cellData[i]))
            h = r.height() + 2 * self.margin
            if height < h:
                height = h
        return height

    def printRow(self, widths, cellData, height, flags):
        x = 0
        for i in range(len(widths)):
            self._painter.drawText(x + self.margin,
                self._currentPageHeight + self.margin,
                widths[i] - self.margin, height - 2 * self.margin,
                flags, str(cellData[i]))
            self._painter.drawRect(x, self._currentPageHeight,
                widths[i], height)
            x += widths[i]
        self._currentPageHeight += height

    def _printFooterRow(self):
        self._painter.setFont(self.footerFont)
        self._painter.drawText(self.margin, self.printer.height() -
            self._footerRowHeight - self.margin, self.printer.width() -
            2 * self.margin, self._footerRowHeight - 2 * self.margin,
            self.footerFlags, "Страница " + str(self._currentPageNumber))

    Пользоваться этим классом очень просто: сначала нужно создать его экземпляр, вызвав конструктор следующего формата:

  <Объект> = PrintList()

    После чего задать параметры печатаемого табличного отчета, воспользовавшись следующими атрибутами класса PrintList:

    Следующие свойства являются необязательными для указания:

    После задания всех необходимых параметров следует вызвать метод printData() класса PrintList, который и выполняет печать данных. Впоследствии, пользуясь тем же экземпляром этого класса, мы можем распечатать другой набор данных.

    В примере ниже приведен код тестового приложения, выводящего на экран числа от 1 до 100, их квадраты и кубы. Подразумевается, что код класса, приведенный в начале этого шага, сохранен в файле PrintList.ру.

from PyQt5 import QtWidgets
import sys
import PrintList

app = QtWidgets.QApplication(sys.argv)
pl = PrintList.PrintList()
# Если требуется вывести документ в файл формата PDF,
# следует раскомментировать эту строку:
# pl.printer.setOutputFileName("output.pdf")
data = []
for b in range(1, 101):
    data.append([b, b ** 2, b ** 3])
pl.data = data
pl.columnWidths = [100, 100, 200]
pl.headers =  ["Аргумент", "Квадрат", "Куб"]
pl.printData()
Архив с файлами можно взять здесь.

    В результате мы должны получить табличный документ из трех страниц с тремя столбцами и нумерацией в "поддоне".

    Фрагмент результирующего pdf-файла изображен на рисунке 1.


Рис.1. Фрагмент вывода результата в pdf-файл

    На следующем шаге мы рассмотрим служебные классы.




Предыдущий шаг Содержание Следующий шаг