ээдд. Прохоренок_Н_А__Дронов_В_А_Python_3_и_PyQt_5_Разработка_приложен. Николай Прохоренок Владимир Дронов
Скачать 7.92 Mb.
|
QPageSize : ps = p.defaultPageSize() print(ps.name()) Выведет: A4 s = ps.size(QtGui.QPageSize.Millimeter) print(s.width(),"x", s.height()) Выведет: 210.0 x 297.0 defaultDuplexMode() — возвращает заданный по умолчанию режим двусторонней печати; minimumPhysicalPageSize() и maximumPhysicalPageSize() — возвращают, соответствен- но, минимальный и максимальный размеры бумаги, поддерживаемые принтером и за- данные в виде экземпляров класса QPageSize : ps = p.maximumPhysicalPageSize() print(ps.name()) Глава 29. Печать документов 723 Выведет: Custom (1190pt x 1916pt) s = ps.size(QtGui.QPageSize.Millimeter) print(s.width(),"x", s.height()) Выведет: 419.81 x 675.92 29.5. Класс QPdfWriter: экспорт в формат PDF В разд. 29.1.1 упоминалось о возможности сохранения печатаемого документа в файл фор- мата PDF — для этого достаточно вызвать метод setOutputFileName() , передав ему в ка- честве параметра путь к файлу и указав у этого файла расширение pdf . Однако при этом задействуется подсистема печати Windows, что приводит к напрасному расходу системных ресурсов. Библиотека PyQt 5 предоставляет возможность экспорта документов в формат PDF напря- мую, без использования подсистемы печати. Это обеспечивает класс QPdfWriter , объявлен- ный в модуле QtGui . Его иерархия наследования: QPaintDevice – (QObject, QPagedPaintDevice) – QPdfWriter Формат конструктора этого класса: <Объект> = QPdfWriter(<Путь к файлу>) В качестве параметра указывается путь к файлу, в который будет экспортирован документ. Вывод документа в формат PDF выполняется так же, как и его печать (см. разд. 29.1.2). Как и QPrinter , класс QPdfWriter поддерживает метод newPage() , подготавливающий следую- щую страницу документа для вывода. Класс QPdfWriter поддерживает также и следующие методы, которые будут нам полезны (полный их список можно найти на странице https://doc.qt.io/qt-5/qpdfwriter.html): setPageSize( — задает размер страницы в виде экземпляра класса QPageSize . Возвращает True , если операция увенчалась успехом, и False — в противном случае; setPageOrientation(<Ориентация>) — задает ориентацию страницы в виде значения ат- рибута Portrait ( 0 , портретная) или Landscape ( 1 , ландшафтная) класса QPageLayout Возвращает True , если операция увенчалась успехом, и False — в противном случае; setPageMargins( — задает отступы от краев стра- ницы в заданной единице измерения. Сами отступы указываются в виде экземпляра класса QMarginsF . Единица измерения указывается в виде значения одного из следующих атрибутов класса QPageLayout : • Millimeter — 0 — миллиметры; • Point — 1 — пункты; • Inch — 2 — дюймы; • Pica — 3 — пики; • Didot — 4 — дидо (0,375 мм); • Cicero — 5 — цицеро (4,5 мм). Возвращает True , если операция увенчалась успехом, и False — в противном случае; 724 Часть II. Библиотека PyQt 5 setPageLayout( — задает сразу все параметры страницы (размеры, ори- ентацию, отступы от краев страницы и т. п.) в виде экземпляра класса QPageLayout . Воз- вращает True , если операция увенчалась успехом, и False — в противном случае; setResolution(<Разрешение>) — задает разрешение в виде целого числа в точках на дюйм; setCreator(<Имя создателя>) — задает имя создателя документа, которое будет записа- но в файл PDF; setTitle(<Заголовок>) — задает заголовок документа, который будет записан в файл PDF. В качестве практического занятия возьмем код, приведенный в листинге 29.1, и немного переделаем его: пусть на первой странице он выводит вместо надписи «QPrinter» строку «QPdfWriter», а в качестве формата бумаги устанавливает A5 (листинг 29.6). Листинг 29.6. Использование класса QPdfWriter from PyQt5 import QtCore, QtWidgets, QtGui, QtPrintSupport import sys app = QtWidgets.QApplication(sys.argv) writer = QtGui.QPdfWriter("output.pdf") writer.setCreator("Владимир Дронов") writer.setTitle("Тест") # Заодно поэкспериментируем с указанием параметров бумаги с помощью # класса QPageLayout layout = QtGui.QPageLayout() layout.setPageSize(QtGui.QPageSize(QtGui.QPageSize.A5)) layout.setOrientation(QtGui.QPageLayout.Portrait) writer.setPageLayout(layout) painter = QtGui.QPainter() painter.begin(writer) color = QtGui.QColor(QtCore.Qt.black) painter.setPen(QtGui.QPen(color)) painter.setBrush(QtGui.QBrush(color)) font = QtGui.QFont("Verdana", pointSize=42) painter.setFont(font) painter.drawText(10, writer.height() // 2 - 50, writer.width() - 20, 50, QtCore.Qt.AlignCenter | QtCore.Qt.TextDontClip, "QPdfWriter") layout.setOrientation(QtGui.QPageLayout.Landscape) writer.setPageLayout(layout) writer.newPage() pixmap = QtGui.QPixmap("img.jpg") pixmap = pixmap.scaled(writer.width(), writer.height(), aspectRatioMode=QtCore.Qt.KeepAspectRatio) painter.drawPixmap(0, 0, pixmap) painter.end() У класса QPdfWriter есть недостаток — создаваемые с его помощью PDF-документы имеют очень большой размер. Так, у авторов после выполнения приведенного в листинге 29.6 кода получился файл объемом в 4,32 Мбайт. Вероятно, PyQt 5 создает документы максимально доступного в формате PDF качества, и понизить его, тем самым уменьшив размер результи- рующих файлов, мы не можем. ГЛ А В А 30 Взаимодействие с Windows PyQt 5 предоставляет весьма богатые средства для взаимодействия с Windows. Мы можем задать значок, отображающийся на кнопке панели задач и перекрывающий значок прило- жения, создать у кнопки наложенный индикатор процесса выполнения, работать со списка- ми быстрого доступа, формировать инструментальную панель на миниатюре, что возникает при наведении курсора на кнопку панели задач. Все это позволит придать нашим PyQt- приложениям подобающий им лоск. Все описанные в этой главе классы определены в модуле QtWinExtras , если не указано иное. 30.1. Управление кнопкой в панели задач Сначала рассмотрим инструменты для управления кнопкой в панели задач, которой пред- ставляется запущенное приложение: смены выводящегося на ней значка и создания нало- женного индикатора процесса. 30.1.1. Класс QWinTaskbarButton Класс QWinTaskbarButton создает кнопку, которая представляет текущее приложение на стандартной панели задач. Формат его конструктора: <Объект> = QWinTaskbarButton([parent=None]) В параметре parent можно указать родителя. Класс QWinTaskbarButton поддерживает следующие методы: setWindow( — задает окно (экземпляр класса QWindow ), которое должна пред- ставлять кнопка. Получить экземпляр упомянутого ранее класса, представляющий окно, можно вызовом метода windowHandle() класса QWidget . Однако здесь нужно иметь в виду, что этот метод способен вернуть корректное значение лишь после того, как окно будет выведено на эк- ран. Поэтому метод setWindow кнопки панели задач следует вызывать внутри переопре- деленного метода showEvent() (за подробностями — к разд. 19.7.1): class MyWindow(QtWidgets.QWidget): def __init__(self, parent=None): 726 Часть II. Библиотека PyQt 5 self.taskbarButton = QtWinExtras.QWinTaskbarButton(parent=self) def showEvent(self, evt): self.taskbarButton.setWindow(self.windowHandle()) window() — возвращает экземпляр класса QWindow , представляющий окно, с которым связана кнопка; setOverlayIcon( — задает новый значок (экземпляр класса QIcon ) для кнопки: taskbarButton = QtWinExtras.QWinTaskbarButton(window) taskbarButton.setOverlayIcon(QtGui.QIcon("taskbar_icon.png")) Метод является слотом. Еще раз отметим, что заданный с применением этого метода значок будет выводиться на кнопке поверх стандартного значка приложения и перекрывать его. Обычно такие знач- ки применяются для обозначения состояния, в котором находится приложение; clearOverlayIcon() — убирает заданный ранее перекрывающий значок. Метод является слотом; overlayIcon() — возвращает экземпляр класса QIcon , представляющий заданный для кнопки перекрывающий значок; setOverlayAccessibleDescription(<Описание>) — указывает описание для перекрываю- щего значка, заданное в виде строки. Метод является слотом; overlayAccessibleDescription() — возвращает описание перекрывающего значка; progress() — возвращает наложенный индикатор процесса (экземпляр класса QWinTaskbarProgress ), заданный для кнопки. Листинг 30.1 представляет код, создающий окно с тремя кнопками, две из которых задают для кнопки панели задач разные перекрывающие значки, а третья убирает значок. Листинг 30.1. Использование класса QWinTaskbarButton from PyQt5 import QtCore, QtWidgets, QtGui, QtWinExtras import sys class MyWindow(QtWidgets.QWidget): def __init__(self, parent=None): QtWidgets.QWidget.__init__(self, parent, flags=QtCore.Qt.Window | QtCore.Qt.MSWindowsFixedSizeDialogHint) self.setWindowTitle("Класс QWinTaskbarButton") # Создаем оба значка self.icon1 = QtGui.QIcon("icon1.png") self.icon2 = QtGui.QIcon("icon2.png") # Создаем кнопку панели задач self.taskbarButton = QtWinExtras.QWinTaskbarButton(parent=self) # Создаем все три кнопки hbox = QtWidgets.QHBoxLayout() btnIcon1 = QtWidgets.QPushButton(self.icon1, "Значок &1") btnIcon1.clicked.connect(self.setIcon1) Глава 30. Взаимодействие с Windows 727 hbox.addWidget(btnIcon1) btnIcon2 = QtWidgets.QPushButton(self.icon2, "Значок &2") btnIcon2.clicked.connect(self.setIcon2) hbox.addWidget(btnIcon2) btnClearIcon = QtWidgets.QPushButton("&Убрать значок") btnClearIcon.clicked.connect(self.taskbarButton.clearOverlayIcon) hbox.addWidget(btnClearIcon) self.setLayout(hbox) self.resize(200, 50) # После вывода окна на экран привязываем его к кнопке панели задач def showEvent(self, evt): self.taskbarButton.setWindow(self.windowHandle()) # Выполняем задание новых значков для кнопки панели задач при нажатии # кнопок def setIcon1(self): self.taskbarButton.setOverlayIcon(self.icon1) def setIcon2(self): self.taskbarButton.setOverlayIcon(self.icon2) app = QtWidgets.QApplication(sys.argv) window = MyWindow() window.show() sys.exit(app.exec_()) 30.1.2. Класс QWinTaskbarProgress Класс QWinTaskbarProgress представляет индикатор процесса, выводящийся на кнопке па- нели задач поверх всех имеющихся на ней значков — как стандартного, так и перекрываю- щего. Создавать экземпляр этого класса вызовом его конструктора нам не придется. Любая кноп- ка панели задач уже имеет такой индикатор, изначально невидимый. Получить его можно вызовом метода progress() класса QWinTaskbarButton Класс QWinTaskbarProgress поддерживает следующие методы: setVisible(<Флаг>) — если передать методу с параметром значение True , индикатор появится на экране. Значение False скрывает индикатор. Метод является слотом; show() — выводит индикатор на экран. Метод является слотом; hide() — скрывает индикатор. Метод является слотом; isVisible() — возвращает True , если индикатор присутствует на экране, и False , если он скрыт; setRange(<Минимум>, <Максимум>) — задает минимальное и максимальное значения для воображаемой шкалы индикатора, указанные в виде целых чисел. Если оба значения равны 0 , индикатор будет находиться в так называемом неопределенном состоянии, и по нему будет бежать бесконечная зеленая волна. Метод является слотом; 728 Часть II. Библиотека PyQt 5 setMinimum(<Минимум>) и setMaximum(<Максимум>) — задают, соответственно, минималь- ное и максимальное значения для воображаемой шкалы индикатора. Оба метода являют- ся слотами; minimum() и maximum() — возвращают, соответственно, минимальное и максимальное значения воображаемой шкалы индикатора; setValue(<Значение>) — указывает значение, отображаемое индикатором в текущий момент. Метод является слотом; value() — возвращает текущее значение, отображаемое индикатором; pause() — ставит индикатор на паузу. Индикатор, поставленный на паузу, выводится желтым цветом. Метод является слотом; stop() — останавливает индикатор. Остановленный индикатор выводится красным цве- том. Метод является слотом; resume() — вновь запускает поставленный на паузу или остановленный индикатор. Работающий индикатор выводится зеленым цветом. Метод является слотом; setPaused(<Флаг>) — если передать методу с параметром значение True , индикатор будет поставлен на паузу, если False — вновь запущен. Метод является слотом; reset() — сбрасывает индикатор, перемотав его на начальное значение воображаемой шкалы. Метод является слотом; isPaused() — возвращает True , если индикатор в текущий момент поставлен на паузу, и False — в противном случае; isStopped() — возвращает True , если индикатор в текущий момент остановлен, и False — в противном случае. Теперь рассмотрим сигналы, поддерживаемые классом QWinTaskbarProgress : visibilityChanged(<Новое состояние>) — генерируется при выводе индикатора на экран или его скрытии. В параметре передается величина True , если индикатор выведен на эк- ран, и False , если он скрыт; valueChanged(<Новое значение>) — генерируется при изменении значения, отображае- мого индикатором. В параметре обработчику передается новое значение; minimumChanged(<Новое минимальное значение>) и maximumChanged(<Новое максимальное значение>) — генерируются при изменении, соответственно, минимального и макси- мального значения у воображаемой шкалы индикатора. В параметре обработчику пере- дается новое значение. Пример приложения, использующего индикатор на кнопке панели задач, приведен в лис- тинге 30.2. Это приложение при нажатии кнопки Пуск последовательно, с секундным про- межутком увеличивает значение индикатора от 0 до 10, позволяя ставить его на паузу, оста- навливать и запускать вновь. Листинг 30.2. Использование класса QWinTaskbarProgress from PyQt5 import QtCore, QtWidgets, QtWinExtras import sys, time class MyWindow(QtWidgets.QWidget): def __init__(self, parent=None): Глава 30. Взаимодействие с Windows 729 QtWidgets.QWidget.__init__(self, parent, flags=QtCore.Qt.Window | QtCore.Qt.MSWindowsFixedSizeDialogHint) self.setWindowTitle("Класс QWinTaskbarProgress") # Создаем кнопку панели задач self.taskbarButton = QtWinExtras.QWinTaskbarButton(parent=self) # Получаем индикатор процесса, задаем его параметры # и делаем его видимым self.progress = self.taskbarButton.progress() self.progress.setRange(0, 10) self.progress.show() # Создаем необходимые кнопки vbox = QtWidgets.QVBoxLayout() btnStart = QtWidgets.QPushButton("&Пуск") btnStart.clicked.connect(self.start) vbox.addWidget(btnStart) btnPause = QtWidgets.QPushButton("Па&уза") btnPause.clicked.connect(self.progress.pause) vbox.addWidget(btnPause) btnStop = QtWidgets.QPushButton("&Стоп") btnStop.clicked.connect(self.progress.stop) vbox.addWidget(btnStop) btnResume = QtWidgets.QPushButton("П&родолжить") btnResume.clicked.connect(self.progress.resume) vbox.addWidget(btnResume) self.setLayout(vbox) self.resize(100, 100) # После вывода окна на экран привязываем его к кнопке панели задач def showEvent(self, evt): self.taskbarButton.setWindow(self.windowHandle()) # При нажатии кнопки "Пуск" последовательно, с секундным промежутком # увеличиваем значение индикатора от 0 до 10, конечно, если индикатор # не поставлен на паузу и не остановлен def start(self): i = 0 while i < 11: if not self.progress.isPaused() and not self.progress.isStopped(): self.progress.setValue(i) i += 1 time.sleep(1) QtWidgets.qApp.processEvents() self.progress.reset() app = QtWidgets.QApplication(sys.argv) window = MyWindow() window.show() sys.exit(app.exec_()) 730 Часть II. Библиотека PyQt 5 Рис. 30.1 показывает три кнопки панели задач, принадлежащие трем разным копиям при- ложения, чей код представлен в листинге 30.2. Каждая кнопка имеет свой индикатор про- цесса: активный (показывающий процесс выполнения какой-либо операции), приостанов- ленный и остановленный. Рис. 30.1. Индикаторы процесса (в порядке слева направо): активный, приостановленный и остановленный 30.2. Списки быстрого доступа Список быстрого доступа появляется при щелчке на кнопке панели задач правой кнопкой мыши и показывает типовые действия, которые можно выполнить с представляемым кноп- кой приложением: закрепление на панели задач, закрытие и, наконец, активизация окна приложения. Однако мы можем программно добавить в этот список свои собственные пункты, предназначенные для открытия каких-либо избранных файлов или запуска каких- либо приложений. Для работы со списками быстрого доступа PyQt предлагает три класса, один из которых представляет сам список, другой — отдельную категорию, к которой относятся те или иные его пункты, а третий — отдельный пункт списка. 30.2.1. Класс QWinJumpList Класс QWinJumpList представляет сам список быстрого доступа. Конструктор этого класса имеет формат: <Объект> = QWinJumpList([parent=None]) В параметре parent можно указать родителя. Класс QWinJumpList поддерживает такие методы: recent() — возвращает стандартную категорию (экземпляр класса QWinJumpListCategory ) недавно открывавшихся документов; frequent() — возвращает стандартную категорию (экземпляр класса QWinJumpListCategory ) часто открываемых документов; tasks() — возвращает стандартную категорию (экземпляр класса QWinJumpListCategory ) задач; addCategory() — добавляет новую произвольную (т. е. создаваемую самим разработчи- ком приложения) категорию в список быстрого доступа. Форматы метода: addCategory( |