Главная страница

ээдд. Прохоренок_Н_А__Дронов_В_А_Python_3_и_PyQt_5_Разработка_приложен. Николай Прохоренок Владимир Дронов


Скачать 7.92 Mb.
НазваниеНиколай Прохоренок Владимир Дронов
Дата05.05.2023
Размер7.92 Mb.
Формат файлаpdf
Имя файлаПрохоренок_Н_А__Дронов_В_А_Python_3_и_PyQt_5_Разработка_приложен.pdf
ТипДокументы
#1111379
страница67 из 83
1   ...   63   64   65   66   67   68   69   70   ...   83

ГЛ А В А
29
Печать документов
PyQt 5 поддерживает ряд развитых средств, позволяющих выполнить печать документов, их предварительный просмотр и экспорт в формат PDF.
Любой установленный в системе принтер представляется классом
QPrinter
. Поскольку он является подклассом класса
QPagedPaintDevice
, который, в свою очередь, наследует рас- смотренный в главе 24 класс
QPaintDevice
, мы можем для вывода документов на печать использовать методы последнего.
Класс
QPrintDialog обеспечивает функциональность диалогового окна выбора принтера, а класс
QPageSetupDialog
— диалогового окна установки параметров страницы. Для предва- рительного просмотра печатаемых документов задействуются классы
QPrintPreviewDialog и
QPrintPreviewWidget
: первый выводит документ в отдельное диалоговое окно, а второй — в специализированный компонент, который мы можем использовать вместе с любыми дру- гими изученными нами компонентами. Класс
QPrinterInfo позволяет выяснить, какие принтеры имеются в наличии, и узнать параметры любого из установленных принтеров.
PyQt 5 поддерживает и экспорт документов в формат Adobe PDF исключительно встроен- ными средствами, без привлечения каких бы то ни было сторонних программ. Для выпол- нения этой задачи служит класс
QPdfWriter
Все описанные в этой главе классы определены в модуле
QtPrintSupport
, если не указано иное.
29.1. Основные средства печати
Вывести документ на принтер в PyQt довольно просто. Почти все, что нам нужно для этого знать, было описано в главе 24.
29.1.1. Класс QPrinter
Как уже говорилось, класс
QPrinter представляет установленный в системе принтер. Его иерархия наследования такова:
QPaintDevice – QPagedPaintDevice – QPrinter
Конструктор класса
QPrinter имеет следующие форматы вызова:
<Объект> = QPrinter([mode=ScreenResolution])
<Объект> = QPrinter([, mode=ScreenResolution])

700
Часть II. Библиотека PyQt 5
Первый формат выбирает для печати принтер по умолчанию. В параметре mode может быть указано разрешение принтера, заданное в виде значения одного из следующих атрибутов класса
QPrinter
:

ScreenResolution

0
— разрешение экрана. Позволяет вывести документ максимально быстро, но в худшем качестве;

HighResolution

2
— разрешение принтера. Печать выполняется качественнее, но мед- леннее.
Второй формат позволяет выбрать произвольный принтер из числа установленных в систе- ме. Этот принтер задается экземпляром класса
QPrinterInfo
, речь о котором пойдет далее.
Класс
QPrinter поддерживает очень много методов, из которых мы рассмотрим лишь наи- более полезные (полный их список можно найти на странице https://doc.qt.io/qt-5/ qprinter.html
).
 setPrinterName(<Имя принтера>)
— выполняет подключение к принтеру с заданным в виде строки именем. Если передать пустую строку, будет выполнено подключение к встроенной в PyQt подсистеме вывода документов в формате PDF;
 printerName()
— возвращает строку с именем принтера, к которому выполнено подклю- чение;
 setOutputFileName(<Путь к файлу>)
— задает путь к файлу, в который будет выведен печатаемый документ (так называемая печать в файл). Если файл имеет расширение pdf
, будет выполнен вывод в формате PDF. В противном случае файл будет сохранен в фор- мате, установленном в вызове метода setOutputFormat()
. Чтобы отключить вывод доку- мента в файл, следует вызвать этот метод, передав ему в качестве параметра пустую строку;
 outputFileName()
— возвращает путь к файлу, в который будет выведен документ вме- сто печати на бумаге;
 setOutputFormat(<Формат вывода>)
— задает формат вывода документа при печати в файл. В качестве параметра передается значение одного из следующих атрибутов класса
QPrinter
:

NativeFormat

0
— будет выполнен вывод во внутреннем формате принтера. Этот режим автоматически устанавливается при создании экземпляра класса
QPrinter и вызове метода setPrinterName()
с указанием имени существующего принтера. Если экземпляр класса подключен к подсистеме вывода в формате PDF, будет выполнено переподключение к принтеру по умолчанию;

PdfFormat

1
— будет выполнен вывод в формате PDF. Этот режим автоматически устанавливается при вызове метода setPrinterName()
с указанием пустой строки;
 outputFormat()
— возвращает обозначение формата вывода документа;
 isValid()
— возвращает
True
, если принтер действительно установлен в системе и готов к работе, и
False
— в противном случае.
 setPageSize()
— задает размер страницы в виде экземпляра класса
QPageSize из модуля
QtGui
. Возвращает
True
, если операция увенчалась успехом, и
False
— в противном случае. Вот пример задания размера бумаги А4: ps = QtGui.QPageSize(QtGui.QPageSize.A4) printer.setPageSize(ps)

Глава 29. Печать документов
701
 setPageOrientation(<Ориентация>)
— задает ориентацию страницы в виде значения ат- рибута
Portrait
(
0
, портретная) или
Landscape
(
1
, ландшафтная) класса
QPageLayout из модуля
QtGui
. Возвращает
True
, если операция увенчалась успехом, и
False
— в против- ном случае;
 setPageMargins(<Слева>, <Сверху>, <Справа>, <Снизу>, <Единица измерения>)
— зада- ет отступы от краев страницы, соответственно, слева, сверху, справа и снизу в заданной единице измерения. Сами отступы указываются в виде вещественных чисел, а единица измерения — в виде значения одного из следующих атрибутов класса
QPageLayout
:

Millimeter

0
— миллиметры;

Point

1
— пункты;

Inch

2
— дюймы;

Pica

3
— пики;

Didot

4
— дидо (0,375 мм);

Cicero

5
— цицеро (4,5 мм).
Возвращает
True
, если операция увенчалась успехом, и
False
— в противном случае.
Вот пример задания отступов в 5 мм со всех сторон страницы: printer.setPageMargins(5, 5, 5, 5, QtGui.QPageLayout.Millimeter)
 setPageLayout()
— задает сразу все параметры страницы (размеры, ори- ентацию и отступы от краев страницы в виде экземпляра класса
QPageLayout
. Возвраща- ет
True
, если операция увенчалась успехом, и
False
— в противном случае;
 pageLayout()
— возвращает экземпляр класса
QPageLayout
, хранящий сведения о разме- ре бумаги, ориентации страницы и величинах отступов от краев страницы;
 setCopyCount(<Количество копий>)
— задает количество копий печатаемого документа;
 copyCount()
— возвращает количество копий печатаемого документа;
 setCollateCopies(<Флаг>)
— если передано значение
True
, каждая копия документа бу- дет отпечатана полностью, прежде чем начнется печать следующей копии. Если пере- дать значение
False
, сначала будут отпечатаны все копии первой страницы, потом все копии второй и т. д.;
 collateCopies()
— возвращает
True
, если каждая копия документа печатается пол- ностью, и
False
— в противном случае;
 setDuplex(<Режим двухсторонней печати>)
— задает режим двусторонней печати в виде значения одного из следующих атрибутов класса
QPrinter
:

DuplexNone

0
— односторонняя печать;

DuplexAuto

1
— двусторонняя печать с автоматическим определением стороны листа, вокруг которой следует его перевернуть;

DuplexLongSide

2
— двусторонняя печать с переворачиванием листа вокруг длин- ной стороны;

DuplexShortSide

3
— двусторонняя печать с переворачиванием листа вокруг ко- роткой стороны;
 duplex()
— возвращает обозначение заданного для принтера режима двусторонней печати;

702
Часть II. Библиотека PyQt 5
 setPrintRange(<Диапазон печати>)
— задает диапазон печати документа в виде значе- ния одного из следующих атрибутов класса
QPrinter
:

AllPages

0
— печатать все страницы;

Selection

1
— печатать только выделенный фрагмент;

PageRange

2
— печатать только заданный диапазон страниц;

CurrentPage

3
— печатать только текущую страницу;
 setFromTo(<Начальная страница>, <Конечная страница>)
— задает диапазон печатаемых страниц в документе;
 fromPage()
— возвращает начальную страницу диапазона печати;
 toPage()
— возвращает конечную страницу диапазона печати;
 setColorMode(<Цветовой режим>)
— задает режим вывода цвета в виде значения атрибу- та
Color
(
1
, цветной) или
Grayscale
(
0
, черно-белый) класса
QPrinter
;
 colorMode()
— возвращает обозначение режима вывода цвета, заданного для принтера;
 setResolution(<Разрешение>)
— задает разрешение для принтера в виде целого числа в точках на дюйм. Если указано неподдерживаемое значение разрешения, будет выстав- лено разрешение, наиболее близкое к заданному;
 resolution()
— возвращает заданное для принтера разрешение;
 setPaperSource(<Источник бумаги>)
— задает источник бумаги для принтера в виде зна- чения одного из следующих атрибутов класса
QPrinter
(здесь приведены лишь наиболее часто используемые источники — полный их список можно найти на странице https://doc.qt.io/qt-5/qprinter.html#PaperSource-enum
):

OnlyOne

0
— единственный лоток принтера или лоток, используемый по умолча- нию;

Lower

1
— нижний лоток;

Middle

2
— средний лоток;

Manual

3
— лоток для ручной подачи бумаги;

Envelope

4
— лоток для конвертов;

EnvelopeManual

5
— лоток для ручной подачи конвертов;

Auto

6
— автоматический выбор источника;
 paperSource()
— возвращает обозначение источника бумаги;
 setFontEmbeddingEnabled(<Флаг>)
— если передано значение
True
, в создаваемый доку- мент PDF будут внедрены все использованные в его тексте шрифты, если передано зна- чение
False
— не будут;
 supportsMultipleCopies()
— возвращает
True
, если принтер сам способен напечатать несколько копий документа, и
False
— в противном случае;
 supportedResolutions()
— возвращает список разрешений, поддерживаемых принтером и измеряемых в точках на дюйм: printer = QtPrintSupport.QPrinter() for f in printer.supportedResolutions(): print(f, end = " ")
У авторов вывел:
600

Глава 29. Печать документов
703
Как видим, принтер авторов, установленный по умолчанию, поддерживает лишь разре- шение 600 точек на дюйм.
В
НИМАНИЕ
!
Для некоторых принтеров метод supportResolutions() по какой-то причине выводит пус- той список.
29.1.2. Вывод на печать
Процесс вывода документа на печать средствами PyQt можно разбить на следующие этапы:
1. Создание принтера (экземпляра класса
QPrinter
) и задание его параметров: printer = QtPrintSupport.QPrinter()
2. Создание экземпляра класса
QPainter
: painter = QtGui.QPainter()
3. Вызов метода begin()
класса
QPainter и передача ему в качестве пара- метров только что созданного принтера: painter.begin(printer)
Метод begin()
инициирует процесс вывода графики на принтер. Он возвращает
True
, если инициализация прошла успешно, и
False
— в противном случае.
4. Выполнение вывода необходимой графики, составляющей собственно содержимое документа, средствами класса
QPainter
(см. главу 24).
5. В случае необходимости начать вывод новой страницы — вызов метода newPage()
клас- са
QPrinter
: printer.newPage()
Метод newPage()
подготавливает принтер к выводу новой страницы и возвращает
True
, если подготовка увенчалась успехом, и
False
— в противном случае.
6. По окончании вывода документа — вызов метода end()
класса
QPainter
: painter.end()
Этот метод завершает рисование графики и возвращает
True
, если вывод графики был закончен успешно, и
False
— в противном случае. После его вызова выполняется собст- венно печать документа.
Перед началом вывода графики нам понадобится определить размеры всей страницы прин- тера, размеры области на ней, доступной для рисования, и некоторые другие параметры, касающиеся этих размеров. Для этого мы воспользуемся следующими методами класса
QPrinter
(полный список их можно найти на страницах https://doc.qt.io/qt-5/qprinter.html и https://doc.qt.io/qt-5/qpaintdevice.html):
 width()
— возвращает ширину области, доступной для вывода графики, в пикселах;
 height()
— возвращает высоту области, доступной для вывода графики, в пикселах;
 widthMM()
— возвращает ширину области, доступной для вывода графики, в милли- метрах;
 heightMM()
— возвращает высоту области, доступной для вывода графики, в миллимет- рах;

704
Часть II. Библиотека PyQt 5
 colorCount()
— возвращает количество цветов, которые способен выводить принтер;
 pageRect(<Единица измерения>)
— возвращает размеры области на странице, доступной для вывода графики, в виде экземпляра класса
QRectF
. Единица измерения задается в виде значения одного из следующих атрибутов класса
QPrinter
:

Millimeter

0
— миллиметры;

Point

1
— пункты;

Inch

2
— дюймы;

Pica

3
— пики;

Didot

4
— дидо (0,375 мм);

Cicero

5
— цицеро (4,5 мм);

DevicePixel

6
— пикселы;
 paperRect([<Единица измерения>])
— возвращает размеры страницы целиком в виде экземпляра класса
QRectF
. Единица измерения задается в виде значения одного из атри- бутов класса
QPrinter
, приведенных ранее в описании метода pageRect()
Начало координат находится в левом верхнем углу области, отведенной под вывод графи- ки, — лишь в этой области мы можем выводить графику. Горизонтальная координатная ось направлена направо, а вертикальная — вниз.
Для примера напишем код, который будет выводить на установленный по умолчанию принтер документ из двух страниц (листинг 29.1). Первую страницу мы обведем точечной синей рамкой, а по ее центру расположим надпись «QPrinter». Вторая страница будет отпе- чатана в ландшафтной ориентации, и ее полностью займет графическое изображение.
Листинг 29.1. Использование класса QPrinter from PyQt5 import QtCore, QtWidgets, QtGui, QtPrintSupport import sys app = QtWidgets.QApplication(sys.argv)
# Создаем принтер printer = QtPrintSupport.QPrinter()
# Для целей отладки лучше выводить документ не на принтер,
# а в файл в формате PDF. Чтобы сделать это, достаточно
# раскомментировать следующую строчку кода:
# printer.setOutputFileName("output.pdf")
# Создаем поверхность рисования и привязываем ее к принтеру painter = QtGui.QPainter() painter.begin(printer)
# Рисуем рамку вокруг страницы pen = QtGui.QPen(QtGui.QColor(QtCore.Qt.blue), 5, style = QtCore.Qt.DotLine) painter.setPen(pen) painter.setBrush(QtCore.Qt.NoBrush) painter.drawRect(0, 0, printer.width(), printer.height())
# Выводим надпись color = QtGui.QColor(QtCore.Qt.black) painter.setPen(QtGui.QPen(color)) painter.setBrush(QtGui.QBrush(color))

Глава 29. Печать документов
705 font = QtGui.QFont("Verdana", pointSize = 42) painter.setFont(font) painter.drawText(10, printer.height() // 2 - 100, printer.width() - 20,
50, QtCore.Qt.AlignCenter |
QtCore.Qt.TextDontClip, "QPrinter")
# Изменяем ориентацию страницы. Сделать это нужно перед вызовом
# метода newPage() printer.setPageOrientation(QtGui.QPageLayout.Landscape)
# Переходим на новую страницу printer.newPage()
# Выводим изображение pixmap = QtGui.QPixmap("img.jpg") pixmap = pixmap.scaled(printer.width(), printer.height(), aspectRatioMode = QtCore.Qt.KeepAspectRatio) painter.drawPixmap(0, 0, pixmap) painter.end()
В листинге 29.2 приведен код класса
PrintList
, реализующий печать списков или содержи- мого таблиц баз данных в виде полноценного табличного отчета. Этот класс можно исполь- зовать для разработки бизнес-приложений.
Листинг 29.2. Класс 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

706
Часть II. Библиотека PyQt 5 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,
1   ...   63   64   65   66   67   68   69   70   ...   83


написать администратору сайта