ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 05.12.2023
Просмотров: 883
Скачиваний: 3
ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
СОДЕРЖАНИЕ
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
Глава 29. Печать документов
707 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
:
headers
— заголовки для столбцов табличного отчета в виде списка строк;
columnWidths
— значения ширины для столбцов, измеряемые в пикселах, в виде списка целочисленных величин;
data
— собственно выводимые данные. Они должны представлять собой список значе- ний, выводимых в отдельных ячейках, — каждый из элементов этого списка задает дан- ные для одной строки.
Следующие свойства являются необязательными для указания:
printer
— задает принтер (ссылку на экземпляр класса
QPrinter
), через который отчет выводится на печать. Изначально хранит принтер, используемый по умолчанию;
headerFont
— шрифт, используемый для вывода текста «шапки» табличного отчета. По умолчанию — полужирный шрифт Arial размером 10 пунктов;
headerPen
— параметры рамки, рисуемой вокруг ячеек «шапки». По умолчанию — чер- ная линия толщиной 2 пиксела;
headerFlags
— параметры вывода текста ячеек «шапки». По умолчанию — выравнива- ние по центру и перенос по словам;
bodyFont
— шрифт, используемый для вывода текста обычных строк. По умолчанию — шрифт Arial размером 10 пунктов;
bodyPen
— параметры рамки, рисуемой вокруг ячеек обычных строк. По умолчанию — черная линия толщиной 1 пиксел;
bodyFlags
— параметры вывода текста ячеек обычных строк. По умолчанию — перенос по словам;
footerFont
— шрифт, используемый для вывода текста «поддона» таблицы. По умолча- нию — курсивный шрифт Arial размером 9 пунктов;
footerFlags
— параметры вывода текста «поддона». По умолчанию — выравнивание по центру и перенос по словам;
708
Часть II. Библиотека PyQt 5
margin
— величина просвета между рамкой ячейки и ее содержимым. По умолчанию —
5 пикселов.
После задания всех необходимых параметров следует вызвать метод printData()
класса
PrintList
, который и выполняет печать данных. Впоследствии, пользуясь тем же экземпля- ром этого класса, мы можем распечатать другой набор данных.
В листинге 29.3 приведен код тестового приложения, выводящего на экран числа от 1 до 100, их квадраты и кубы. Подразумевается, что код, приведенный в листинге 29.2, со- хранен в файле
PrintList.py
Листинг 29.3. Тестовое приложение для проверки класса 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()
В результате мы должны получить табличный документ из трех страниц с тремя столбцами и нумерацией в «поддоне».
29.1.3. Служебные классы
PyQt 5 предоставляет нам два служебных класса, позволяющих описать параметры исполь- зуемой для печати бумаги, величины отступов от края страницы или же все это сразу.
29.1.3.1. Класс QPageSize
Класс
QPageSize
, объявленный в модуле
QtGui
, описывает размеры, или, говоря другими словами, формат бумаги, на которой осуществляется печать. Для указания размера бумаги, который будет использовать принтер, предназначен метод setPageSize()
класса
QPrinter
Форматы конструкторов класса:
<Объект> = QPageSize()
<Объект> = QPageSize(<Идентификатор размера бумаги>)
<Объект> = QPageSize(
<Объект> = QPageSize(
<Объект> = QPageSize(
Глава 29. Печать документов
709
Первый формат создает «пустой» экземпляр класса, не хранящий данные ни о каком разме- ре бумаги.
Второй формат позволяет указать размер сразу, в виде значения одного из следующих ат- рибутов класса
QPageSize
(здесь приведены только наиболее употребительные размеры — полный их список можно найти на странице https://doc.qt.io/qt-5/qpagesize.html#
PageSizeId-enum
):
A0
(
5
),
A1
(
6
),
A2
(
7
),
A3
(
8
),
A4
(
0
),
A5
(
9
),
Letter
(
2
),
Legal
(
3
).
Третий и четвертый форматы служат для создания нестандартных размеров бумаги, при этом третий формат принимает в качестве первого параметра экземпляр класса
QSize
(см. разд. 18.5.2), указывающий сами размеры в пунктах. В параметре name можно задать имя создаваемого размера бумаги — если он не указан, будет создано имя по умолчанию вида
Custom (<Ширина> x <Высота>)
Если заданные размеры близки к размерам какого-либо из стандартных форматов бумаги, будет использован этот формат. В параметре matchPolicy можно задать режим подбора стандартного формата бумаги в виде одного из следующих атрибутов класса
QPageSize
:
FuzzyMatch
—
0
— размеры стандартного формата должны быть близки к заданным в конструкторе размерам в определенных рамках с учетом ориентации;
FuzzyOrientationMatch
—
1
— размеры стандартного формата должны быть близки к заданным в конструкторе размерам в определенных рамках без учета ориентации;
ExactMatch
—
2
— размеры стандартного формата должны точно совпадать с заданными в конструкторе.
Четвертый формат принимает в качестве первого параметра экземпляр класса
QSizeF
, ука- зывающий размеры бумаги. Вторым параметром должна быть задана единица измерения размеров в виде значения одного из следующих атрибутов класса
QPageSize
:
•
Millimeter
—
0
— миллиметры;
•
Point
—
1
— пункты;
•
Inch
—
2
— дюймы;
•
Pica
—
3
— пики;
•
Didot
—
4
— дидо (0,375 мм);
•
Cicero
—
5
— цицеро (4,5 мм).
Последний формат позволяет создать копию указанного в параметре экземпляра класса
QPageSize
Примеры:
# Задаем размер бумаги A5 ps = QtGui.QPageSize(QtGui.QPageSize.A5) printer.setPageSize(ps)
# Задаем размер бумаги 100 х 100 пунктов с названием "Особый размер" sz = QtCore.QSize(400, 300) ps = QtGui.QPageSize(sz, name="Особый размер",
matchPolicy=QtGui.QPageSize.FuzzyMatch) pl.printer.setPageSize(ps)
Класс
QPageSize поддерживает следующие полезные для нас методы (полный их список можно найти на странице https://doc.qt.io/qt-5/qpagesize.html):
710
Часть II. Библиотека PyQt 5
size(<Единица измерения>)
и rect(<Единица измерения>)
— возвращают размеры бума- ги в заданных единицах измерения в виде экземпляра класса
QSizeF
или
QRectF
соответ- ственно;
size(<Идентификатор размера бумаги>, <Единица измерения>)
— возвращает размеры бумаги для заданного идентификатора формата в заданных единицах измерения, пред- ставленные экземпляром класса
QSizeF
: s = QtGui.QPageSize.size(QtGui.QPageSize.A0, QtGui.QPageSize.Millimeter) print(s.width(), "x", s.height())
Выведет:
841.0 x 1189.0
Метод является статическим;
sizePixels(<Разрешение>)
и rectPixels(<Разрешение>)
— возвращают размеры бумаги в пикселах для заданного разрешения, которое измеряется в точках на дюйм. Результат представляет собой экземпляр класса
QSize или
QRect соответственно: ps = QtGui.QPageSize(QtGui.QPageSize.A5) s = ps.sizePixels(600) print(s.width(), "x", s.height())
Выведет:
3500 x 4958
sizePixels(<Идентификатор размера бумаги>, <Разрешение>)
— возвращает размеры бумаги в пикселах для заданных идентификатора формата и разрешения, которое изме- ряется в точках на дюйм. Результат представляет собой экземпляр класса
QSize
. Метод является статическим;
sizePoints()
и rectPoints()
— возвращают размеры бумаги в пунктах в виде экземпля- ра класса
QSize или
QRect соответственно;
sizePoints(<Идентификатор размера бумаги>)
— возвращает размеры бумаги в пунктах для заданного идентификатора размера в виде экземпляра класса
QSize
. Метод является статическим;
swap(
— меняет размер бумаги, хранящийся в текущем экземпляре класса, на заданный в параметре;
name()
— возвращает имя формата бумаги;
name(<Идентификатор размера бумаги>)
— возвращает имя формата бумаги, заданного идентификатором. Метод является статическим;
isEquivalentTo(
— возвращает
True
, если размеры текущего формата бу- маги равны размерам формата, переданного в параметре, и
False
— в противном случае.
Также класс
QPageSize поддерживает операторы сравнения
==
и
!=
: s1 = QtGui.QPageSize(QtGui.QPageSize.A4) s2 = QtGui.QPageSize(QtGui.QPageSize.A4) s3 = QtGui.QPageSize(QtGui.QPageSize.A3) print(s1 == s2) # Выведет: True print(s1 != s3) # Выведет: True
29.1.3.2. Класс QPageLayout
Класс
QPageLayout
, также объявленный в модуле
QtGui
, представляет сразу размеры, ориен- тацию страницы и величины отступов от краев страницы. Передать все эти сведения прин- теру позволяет метод setPageLayout()
класса
QPrinter