Руководство по работе с библиотекой Qt с использованием Python 3
Установка необходимых компонентов для работы
-
Установить Python версии не менее 3.5.
В операционных системах семейства Windows процесс установки сводится к скачиванию установщика с сайта https://www.python.org и его запуска.
В операционных система семейства Unix процесс установки сводится к запуску пакетного менеджера с выбором необходимого пакета.
Пример установки Python 3 в Ubuntu:
sudo apt-get install python3
По умолчанию, путь к интерпретатору Python 3 при установке на любой операционной системе добавляется к переменной среды PATH. В Windows для запуска интепретатора достаточно набрать в консоли:
В Unix системах, как правило, может быть уже установлена более ранняя версия интерпретатора, поэтому для корректного запуска 3-ей ветки Python рекомендуется выполнить в терминале команду:
-
В Python установка сторонних библиотек (или пакетов) происходит с помощью пакетного менеджера pip.
По умолчанию, в Windows при установке самого интерпретатора устанвливается и пакетный менеджер.
В Unix системах установка пакетного менеджера pip происходит отдельно.
Пример установки pip в Ubuntu:
sudo apt-get install python3-pip
Установка сторонних пакетов (библиотек) сводится к следующей команде в терминале Unix/консоли Windows:
pip3 install название_стороннего_пакета
pip автоматически найдет, скачает и установит необходимый пакет из сети интернет.
-
Для установки библиотеки Qt следует выполнить следующую команду:
Основы работы с Qt
Библиотека Qt является кросплатформенной и предназначена для написания графических приложений. Она инкапсулирует в себе все основные понятия любой из операционных графических систем: окна, фреймы, модальные диалоги, кнопки, текстовые поля, панели и т.д. Ядро библиотеки и всех ее компонентов написаны на языке программирования C++. Библиотека не является монолитной и разбита на несколько основных модулей, которые содержат классы для работы с графикой, сетью, файлами, аудио/видео, потоками ОС и т.д.
Пакет PyQt5 является портом для работы с Qt на языке Python. Ввиду этого, пакет наследует основные названия модулей библиотеки и их классов. Однако, в отличие от процесса работы на C++ под Qt, работа на языке Python с использованием пакета PyQt5 избавляет программиста от низкоуровневых особенностей C++ и ускоряет процесс написания программного кода. В пользу PyQt5 стоит сказать, что скорость понимания абстракций графического интерфейса, написанных на языке Python, бывает более высокой, нежели на C++.
Как правило, процесс ознакомления с PyQt5 тесно связан с чтением документации по тому или иному классу. Однако, стоит заметить, что все описания классов модулей Qt представлены на языке C++. Но такие понятия, как классы, его атрибуты и методы в языке C++ интуитивно легко перекладываются на язык Python. Тем самым, любые описания и примеры использования того или иного атрибута/метода на языке C++ в документации Qt справедливы и для Python, где любые упоминания про указатели и ссылки просто опускаются при работы с PyQt5.
На данный момент библиотека Qt развивается в двух направлениях: Qt Widgets и Qt Quick. Qt Widgets является фундаментальным и базовым направлением библиотеки. Данный модуль существует с момента сущестования платформы и направлен на создания графических приложений в стиле объектно-ориентированного подхода, где любой компонент интерфейса представлен объектом класса, тем самым организуя весть графический интерфейс пользователя в иерархию объектов. Qt Quick является более современным ответвлением платформы Qt. Данное направление вводит новые высокоуровневые абстракции вроде машины конечного автомата и вносит принципы реактивного программирования. Также, Qt Quick предлагает идею декларативного описания пользовательского интерфейса средствами JavaScript подобного языка QML.
В данном руководстве описываются базовые принципы работы с Qt Widgets совместно с пакетом PyQt5.
Ссылка на документацию Qt 5: http://doc.qt.io/qt-5/qtwidgets-index.html
Ссылка на документацию PyQt5: http://pyqt.sourceforge.net/Docs/PyQt5
1. Основной цикл обработки событий
Приложение Qt построено на основе бесконечного цикла, который обратывает события: события операционной системы, события пользоваля приложения (поведение мыши, использование клавиатуры). Для запуска минимального приложения, следует передать циклу контекст, в котором начнут обрабатываться события. Базовым контекстом является понятие Виджет, которое представлено классом QWidget.
Виджет — это аналог окна, которое как может иметь рамку, кнопки сворачивания и закрытия, а может их и не иметь. С точки зрения операционных систем, это именно контекст, где операционная система может реагировать на события пользователя. В Qt виджеты могут содержать иерархию из других виджетов. При этом, разработчик никак не ограничен тем, как будет выглядеть виджет. Им могут быть как стандартное текстовое поле, кнопка, текстовая метка, так и сложный графический объект со своим стилем прорисовки.
Минимальное приложение Qt состоит из определения класса наследника QWidget, создания его экземпляра и запуска бесконечного цикла обработки событий.
import sys
from PyQt5.QtWidgets import QWidget, QApplication, QVBoxLayout, QLabel
class MyWidget(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self._initUI()
def _initUI(self):
self.label = QLabel('Hello', self)
self.layout = QVBoxLayout(self)
self.layout.addWidget(self.label)
self.setLayout(self.layout)
self.setGeometry(0, 0, 100, 100)
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
myWidget = MyWidget()
sys.exit(app.exec_())
2. Виджеты
Как было сказано, виджет представлен классом QWidget. Для создания виджета следует определить класс-наследник QWidget. В конструкторе класса следует добавить последний аргумент по умолчанию parent и вызвать инструкцию:
Параметр parent указывает на родительский виджет описываемого. Если описываемый является корневым, parent = None. Стоит сказать, что создание любого другого дочернего виджета, разметки должно просходить с передачей последним аргументом родительского виджета parent. Наиболее часто, родителем оказывается описываемый виджет self.
Часто, виджетам устанавливают ту или иную разметку, по правилам которой внутри располагаются другие виджеты. Наиболее используемыми классами разметки являются QVBoxLayout (вертикальная разметка) и QHBoxLayout (горизонтальная разметка). Для добавления дочерних виджетов в разметку предназачен метод addWidget(QWidget). Чтобы установить виджету ту или иную разметку используется метод setLayout(QLayout).
Хорошим стилем считается создание всех дочерних разметок/виджетов описываемого в теле контструктора класса. Как правило, создается приватный метод, например _initUI, и вызывается в конструкторе __init__.
Qt предоставляет набор удобных стандартных виджетов, поведение которых также можно изменить определением нового класса-наследника.
2.1 Текстовая метка: QLabel
Пример использования:
from PyQt5.QtWidgets import QLabel
...
self.label = QLabel('Text', self)
Часто используемые методы:
- text() → string: возвращает текст метки.
- setText(string): устанавливает текст метки.
2.2 Текстовое поле: QLineEdit
Пример использования
from PyQt5.QtWidgets import QLineEdit
...
self.edit = QLineEdit('текст в поле ввода', self)
Часто используемые методы:
- text() → string: возвращает текст поля ввода.
- setText(string): устанавливает текст поля ввода.
2.3 Кнопка: QPushButton
Пример использования
from PyQt5.QtWidgets import QPushButton
...
self.button = QPushButton('Текст на кнопке', self)
Часто используемые методы:
- setText(string): устанавливает текст на кнопке.
2.4 Многострочное поле ввода: QTextEdit
Пример использования
from PyQt5.QtWidgets import QTextEdit
...
self.muli_edit = QTextEdit(self)
Часто используемые методы:
- setText(string): устанавливает текст в поле ввода.
- toPlainText() → string: возвращает обычный текст.
- toHtml() → string: возврашает текст в формате HTML.
2.5 Слайдер: QSlider
Пример использования
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QSlider
...
self.slider = QSlider(Qt.Horizontal, self)
Часто используемые методы:
- setTickInterval(int): устанавливает шаг.
- tickInterval() → int: возвращает шаг.
- setMinimum(int): устанавливает минимальное значение.
- setMaximum(int): устанавливает максимальное значение.
2.6 Чек-бокс: QCheckBox
Пример использования
from PyQt5.QtWidgets import QCheckBox
...
self.checkbox = QCheckBox('Метка чек-бокса', self)
Часто используемые методы:
- toogle(): ставит/снимает чек-бокс.
3. Взаимодействие с пользователем: введение в сигналы/слоты
В библиотеке Qt любые из классов, которые являются наследниками класса QObject могут участвовать в механизме сигналов/слотов. Практически все классы Qt являются наследниками QObject, в том числе и виджеты.
Механизм сигналов/слотов — является базовым понятием в обработке событий. Событиями могут выступать: действия пользователя графического интерфейса, события операционной системы и т.д. Само понятие события в Qt носит название Сигнал. Реакция на сигнал это всегда какая-либо простая функция, которая носит название Слот.
Как правило, дочерние компоненты описываемого виджета генерируют какие-либо сигналы. Например, сигнал клика по кнопке. Для реакции на данное событие создается метод внтури описываемого виджета. Стоит упомянуть, что сигнал может передавать любую порцию информации: число, строка, список и т.д.. Если сигнал отправляет какие-либо данные, то в методе на реакцию данного сигнала должен передаваться аргумент(ы) для обработки передаваемой информации.
Пример использования механизма сигналов/слотов:
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (QWidget, QLCDNumber, QSlider,
QVBoxLayout, QApplication)
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
lcd = QLCDNumber(self)
sld = QSlider(Qt.Horizontal, self)
vbox = QVBoxLayout()
vbox.addWidget(lcd)
vbox.addWidget(sld)
self.setLayout(vbox)
sld.valueChanged.connect(lcd.display)
self.setGeometry(300, 300, 250, 150)
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
Как видно из примера, виджет sld генерирует сигнал valueChanged, информирующий об изменении позиции слайдера. В свою очередь, данный сигнал связан с методом display виджета lcd. В данном случае, valueChanged является сигналом и отсылает значение типа int, а display является методом-сигналом, в который передается значение типа int. Связывание сигнала и слота происходит с помощью метода сигнала connect, который имеется у любого сигнала Qt.
Для определения слота, следует создать метод у класса описываемого виджета и привязать нужный сигнал к новому слоту с помощью метода сигнала connect.
Пример определения слота:
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (QWidget, QApplication, QVBoxLayout,
QLabel, QPushButton)
class MyWidget(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self._initUI()
def _initUI(self):
self.label = QLabel('Push the Button', self)
self.button = QPushButton('Push', self)
self.button.clicked.connect(self._handleClickButton)
self.layout = QVBoxLayout(self)
self.layout.addWidget(self.label)
self.layout.addWidget(self.button)
self.setLayout(self.layout)
self.show()
def _handleClickButton(self):
self.label.setText('Push Done.')
if __name__ == '__main__':
app = QApplication(sys.argv)
myWidget = MyWidget()
sys.exit(app.exec_())
Чтобы определить слот, который реагирует на сигналы, отправляющие какую-либо информацию, следует лишь добавить аргумент(ы).
Пример определения слота на сигнал, передающий значение типа int:
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (QWidget, QApplication, QVBoxLayout,
QLabel, QSlider)
class MyWidget(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self._initUI()
def _initUI(self):
self.label = QLabel('Change Slider', self)
self.slider = QSlider(Qt.Horizontal, self)
self.slider.valueChanged.connect(self._handleChangeSlider)
self.layout = QVBoxLayout(self)
self.layout.addWidget(self.label)
self.layout.addWidget(self.slider)
self.setLayout(self.layout)
self.show()
def _handleChangeSlider(self, value):
self.label.setText(str(value))
if __name__ == '__main__':
app = QApplication(sys.argv)
myWidget = MyWidget()
sys.exit(app.exec_())
Виджет slider генерирует сигнал valueChanged при изменении слайдера. В свою очередь, данный сигнал связан с слотом/методом _handleChangeSlider, который принимает аргумент value типа int. При любом изменении слайдера вызывается метод _handleChangeSlider, который устанавливает текст метке label на значение ползунка слайдера. Стоит сказать, что метод метки label.setText принимает строковое значение, поэтому значение, отправляемое сигналом, числового типа int явно приводится к строковому типу str.
В документации библиотеки Qt к тому или иному классу виджета все сигналы находятся в секции Signals. Особое внимание стоит обращать на типы данных, которые возвращают сигналы.
В этом руководстве по PyQt5 будет показано, как использовать Python 3 и Qt для создания графического интерфейса пользователя в Windows, Mac или Linux. Мы даже расскажем, как самостоятельно написать установщик.
PyQt — это библиотека, которая позволяет использовать фреймворк Qt GUI (GUI — это графический интерфейс пользователя) в Python. Сам Qt, как известно, написан на C++. Используя его в Python, вы можете создавать приложения намного быстрее, не жертвуя при этом значительной частью производительности C++.
PyQt5 это самая последняя, пятая версия Qt. Еще можно найти в интернете случайное упоминание PyQt4, но эта версия устарела и больше не поддерживается.
Новый интересный конкурент PyQt — это Qt for Python. Она обладает практически идентичным API, но в отличие от PyQt имеет лицензию LGPL и, следовательно, может использоваться бесплатно даже в коммерческих проектах. Она поддерживается компанией Qt, а значит, скорее всего, за ней будущее. Здесь мы используем PyQt, потому что она более зрелая. Но, так как их интерфейсы очень похожи, вы всегда можете перейти на Qt for Python позднее.
Установка PyQt
Лучший способ управлять зависимостями в Python — через виртуальную среду. Виртуальная среда — это просто локальный каталог, содержащий библиотеки для данного конкретного проекта. В отличии от общесистемной установки библиотек, это не не повлияет на другие ваши проекты.
Для создания виртуальной среды в текущем каталоге выполните следующую команду:
python3 -m venv venv
Эта команда создаст директорию venv/
. Чтобы активировать виртуальную среду в Windows, выполните следующую команду:
call venv/scripts/activate.bat
А для Mac и Linux вот эту:
source venv/bin/activate
То, что виртуальная среда активирована, вы можете увидеть по префиксу (venv)
в командной строке:
Теперь, чтобы установить PyQt, выполните следующую команду:
pip install PyQt5==5.9.2
Мы используем версию 5.9.2
, потому что не все версии PyQt одинаково стабильны. Данная версия гарантированно будет работать хорошо.
Итак, поздравляем! Вы только что успешно установили PyQt5.
Создание GUI (графического интерфейса пользователя)
Теперь самое время написать ваш первый графический интерфейс! В нашей виртуальной среде запустим Python и выполним следующие команды:
Сначала мы загружаем библиотеку PyQt при помощи оператора import
:
from PyQt5.QtWidgets import QApplication, QLabel
Затем мы создаем QApplication
при помощи следующей команды:
app = QApplication([])
Это обязательное требование библиотеки Qt: каждое приложение с графическим интерфейсом пользователя должно иметь ровно один экземпляр класса QApplication
. До выполнения данной строки многие вещи в Qt просто не работают. Поэтому такая команда будет присутствовать в каждом вашем Qt приложении.
Скобки []
в данной команде представляют аргументы командной строки, переданные приложению. Поскольку наше приложение не использует никаких параметров, мы оставляем скобки пустыми.
Теперь, чтобы реально что-нибудь увидеть, мы создаем следующее сообщение:
label = QLabel('Hello World!')
Затем мы даем команду вывести это на экран:
label.show()
Эта команда покажет небольшое окошко (его вид зависит от вашей операционной системы):
Последний шаг — передача управления библиотеке Qt и указание «запустить приложение, пока пользователь не закроет его». Это делается так:
app.exec_()
Если все это сработало, как ожидалось, тогда супер! Вы только что создали при помощи Python и библиотеки Qt свое первое приложение с графическим интерфейсом.
Виджеты
Все, что вы видите в приложениях PyQt, называется виджетами. Кнопки, сообщения, окна, диалоговые окна, индикаторы выполнения и так далее — все это виджеты. Подобно html
элементам, виджеты в Qt зачастую вложены друг в друга. Например, окно может содержать кнопку, а кнопка, в свою очередь, — сообщение.
На следующей картинке показаны наиболее распространенные виджеты Qt:
Они перечислены ниже в порядке сверху вниз и слева направо:
- QLabel
- QComboBox
- QCheckBox
- QRadioButton
- QPushButton
- QTableWidget
- QLineEdit
- QSlider
- QProgressBar
Отсюда вы можете загрузить, если хотите, код приложения, которое создает такое окно.
Макеты
Как и в приведенном выше примере, ваш графический интерфейс, скорее всего, будет состоять из нескольких виджетов. В этом случае вам нужно указать Qt, как их расположить. Например, вы можете использовать QVBoxLayout для вертикального расположения виджетов:
Вот код, создающий интерфейс, изображенный на картинке выше:
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QVBoxLayout app = QApplication([]) window = QWidget() layout = QVBoxLayout() layout.addWidget(QPushButton('Top')) layout.addWidget(QPushButton('Bottom')) window.setLayout(layout) window.show() app.exec_()
Как и ранее, мы создали экземляр класса QApplication
. Затем мы создаем само окно (window
). Мы используем для него самый простой тип QWidget
, так как он просто используется как контейнер, а никакого особого поведения нам задавать не нужно. Затем мы создаем макет (layout
) и добавляем к нему две кнопки QPushButton
. Наконец, мы говорим окну использовать именно этот макет (и, следовательно, его содержимое). Как и в нашем первом приложении, мы заканчиваем вызовами методов .show ()
и app.exec_ ()
.
Безусловно, существует большое количество разных макетов, например QHBoxLayout
для размещения элементов в ряд. Более подробно с ними можно ознакомиться в документации Qt.
Пользовательские стили
Одной из сильных сторон Qt является поддержка пользовательских стилей. Существует множество механизмов, позволяющих настраивать внешний вид вашего приложения. В этом разделе описаны некоторые из них.
Встроенные стили
Самый грубый способ изменить внешний вид вашего приложения — установить глобальный стиль. Вспомните изображение виджетов, которое мы уже приводили выше:
Здесь используется стиль под названием Fusion
. Если вместо этого использовать стиль Windows
, это будет выглядеть следующим образом:
Чтобы применить стиль, нужно использовать метод app.setStyle (…)
:
from PyQt5.QtWidgets import * app = QApplication([]) app.setStyle('Fusion') ...
Доступные стили зависят от вашей платформы, но обычно они включают в себя «Fusion», «Windows», «WindowsVista» (только для Windows) и «Macintosh» (только для Mac).
Пользовательские цвета
Если вам нравится стиль, но вы хотите изменить его цвета (например, на темную тему), вы можете использовать QPalette
и app.setPalette (...)
. Например:
from PyQt5.QtCore import Qt from PyQt5.QtGui import QPalette from PyQt5.QtWidgets import QApplication, QPushButton app = QApplication([]) app.setStyle('Fusion') palette = QPalette() palette.setColor(QPalette.ButtonText, Qt.red) app.setPalette(palette) button = QPushButton('Hello World') button.show() app.exec_()
Это изменит цвет текста в кнопках на красный:
Как создать темную тему стиля Fusion, можно посмотреть вот здесь.
Таблицы стилей
В дополнение к вышесказанному вы можете изменить внешний вид своего приложения с помощью таблиц стилей. Это аналог CSS в Qt. Например, мы можем добавить некоторое пространство:
from PyQt5.QtWidgets import QApplication, QPushButton app = QApplication([]) app.setStyleSheet("QPushButton { margin: 10ex; }") button = QPushButton('Hello World') button.show() app.exec_()
Для получения дополнительной информации о таблицах стилей смотрите документацию Qt.
Сигналы и слоты
Qt использует механизм, называемый сигналами (signals), чтобы вы могли реагировать на такие события, как нажатие кнопки пользователем. Следующий пример иллюстрирует это. Код содержит кнопку, при нажатии на которую отображается окно сообщения.
from PyQt5.QtWidgets import * app = QApplication([]) button = QPushButton('Click') def on_button_clicked(): alert = QMessageBox() alert.setText('You clicked the button!') alert.exec_() button.clicked.connect(on_button_clicked) button.show() app.exec_()
Строка button.clicked
— это сигнал, метод .connect (...)
позволяет нам установить на нем так называемый слот. Это просто функция, которая вызывается при поступлении сигнала. В приведенном выше примере наш слот показывает окно сообщения.
Термин «слот» важен при использовании Qt в C++, потому что в C++ слоты должны быть объявлены особым образом. Однако в Python любая функция может быть слотом — мы видели это выше. Поэтому различие между слотами и обычными функциями не имеет для нас большого значения.
Сигналы в Qt используются повсеместно. И, конечно, вы также можете определить свои собственные сигналы. Но это выходит за рамки данного руководства.
Компилируем наше приложение
Теперь у вас есть базовые знания для создания GUI, который реагирует на ввод пользователя. Допустим, вы написали приложение. Оно работает на вашем компьютере. Как передать его другим людям, чтобы они тоже могли его запустить?
Вы можете попросить пользователей вашего приложения установить Python и PyQt, как мы сделали выше, а затем предоставить им свой исходный код. Но это очень утомительно (и обычно непрактично). Вместо этого нам нужен отдельный вариант вашего приложения. То есть двоичный исполняемый файл, который другие люди могут запускать в своих системах, не устанавливая ничего.
В мире Python процесс превращения исходного кода в автономный исполняемый файл называется замораживанием (freezing). Несмотря на наличие множества библиотек, решающих эту проблему, например PyInstaller
, py2exe
, cx_Freeze
, bbfreze
, py2app
и так далее, замораживание приложений PyQt всегда было на удивление непростой проблемой.
Мы будем использовать новую библиотеку под названием fbs
, которая позволяет создавать автономные исполняемые файлы для приложений PyQt. Для ее установки введите команду:
pip install fbs
Затем выполним следующую команду:
fbs startproject
Вам будет предложено ввести несколько значений:
Когда вы введете предложенную команду run
, должно открыться пустое окно:
Это приложение PyQt5, такое же, как и те, что мы видели раньше. Его исходный код находится в src/main/python/main.py в вашем текущем каталоге. Но вот что самое интересное: мы можем использовать fbs, чтобы превратить его в отдельный исполняемый файл!
fbs freeze
Эта команда создает и помещает автономный двоичный файл в папку /MyApp/
вашего текущего каталога. Вы можете отправить его своим друзьям (с той же ОС, что и ваша), и они также смогут запустить ваше приложение!
Бонус: создаем установщик
Библиотека fbs также позволяет вам создать установщик для вашего приложения с помощью команды fbs installer
:
(Если вы работаете в Windows, вам сначала нужно установить NSIS и поместить путь к нему в свой PATH.)
За дополнительной информацией по использованию библиотеки fbs
обратитесь к ее документации.
Итоги
Если вы дошли до этого места — примите наши поздравления. Надеемся, теперь у вас есть хорошее представление о том, как для написания приложений Python можно использовать PyQt (и различные ее части). Мы также узнали, как можно создавать автономные исполняемые файлы и установщики при помощи fbs.
PyQt5 является одним из наиболее часто используемых модулей для создания GUI приложений в Python, и это связанно с его простотой, о которой вы узнаете далее.
Еще одна замечательная особенность, которая вдохновляет разработчиков пользоваться PyQt5 – это PyQt5 Designer, благодаря которому можно создавать сложные GUI приложения достаточно быстро. Вам нужно только перетаскивать свои виджеты для создания собственной формы. У нас есть готовый сборник 54 уроков по другому фреймворку wxPython.
- Создаем простой калькулятор в PyQt5
- Создаем игру Сапёр на PyQt5
- История курса рубля на PyQt5 + XML от ЦБ РФ
Другие фреймворки
- wxPython
- Tkinter
- PyCairo
В данном руководстве по PyQt5, я буду использовать Python 3.6 на Ubuntu и предположение, что вы уже имеете базовое представление о Python.
Есть вопросы по Python?
На нашем форуме вы можете задать любой вопрос и получить ответ от всего нашего сообщества!
Telegram Чат & Канал
Вступите в наш дружный чат по Python и начните общение с единомышленниками! Станьте частью большого сообщества!
Паблик VK
Одно из самых больших сообществ по Python в социальной сети ВК. Видео уроки и книги для вас!
Звучит замечательно! Начнем с установки PyQt5, и затем перейдем к тому, как разрабатывать GUI приложение с примерами.
Краткое содержание
- 1 Установка PyQt5
- 1.1 Установка PyQt5 через pip
- 1.2 Установка PyQt5 из исходников на Linux
- 1.3 Установка PyQt5 из исходников на Windows
- 2 Устанавливаем PyQt5 Designer
- 2.1 Где находится дизайнер PyQt5?
- 3 Как использовать дизайнер PyQt5
- 4 Разница между QDialog, QMainWindow, и QWidget
- 5 Загрузка .ui против конвертации .ui в .py
- 5.1 Загрузка файла .ui в ваш код Python
- 5.2 Конвертация файла .ui в .py file при помощи pyuic5
- 6 Виджет QLabel
- 6.1 Меняем шрифт QLabel
- 6.2 Меняем размер QLabel
- 6.3 Меняем текст в QLabel
- 7 Виджет QLineEdit
- 7.1 Метод setStyleSheet()
- 8 Виджет QPushButton
- 9 Визуальный редактор signal/slot
- 10 Как испускать сигналы в PyQt5
- 10.1 Как использовать сигнал в PyQt5
- 10.2 Переопределение сигнала (события) в PyQt5
- 11 Виджет QComboBox
- 11.1 Получаем все элементы из QComboBox
- 11.2 Выбор одного элемента из QCombobox
- 12 QTableWidget
- 12.1 Очистка содержимого QTableWidget
- 12.2 Заполнение QTableWidget из кода
- 12.3 Делаем QTableWidget нередактируемым (только для чтения)
- 12.4 Заголовок для столбцов в QTableWidget
- 12.5 Как сортировать QTableWidget
- 12.6 Добавляем QComboBox в QTableWidget
- 12.7 QProgressBar в QTableWidget
- 13 Компиляция Python приложения
Установка PyQt5
Существует две версии PyQt5: коммерческая и бесплатная версия GPL, которой мы будем пользоваться в этом руководстве.
Есть два способа установки PyQt5:
- Установка PyQt5 через pip
- Установка PyQt5 из исходников на Linux
Установка PyQt5 через pip
Чтобы установить PyQt5 при помощи pip, выполните следующую команду:
Чтобы убедиться в том, что установка прошла успешно, запустите следующий код:
Если не возникло ни одной ошибки, это значит, что вы успешно установили PyQt5. В случае, если ошибки возникли, возможно это связанно с тем, что вы используете версию Python, которая не поддерживается.
Установка PyQt5 из исходников на Linux
Для установки PyQt5 из исходника, вам нужно сделать следующее:
- Установить SIP;
- Скачать исходник PyQt5;
- Настроить и установить.
Как вы возможно знаете, PyQt5 связывает Python с популярной библиотекой Qt, которая написана на С++.
Инструмент, который создает эту связь, называется SIP. Так что для установки PyQt5 из исходника, вам для начала нужно установить SIP.
Для установки SIP, запустите следующую команду:
sudo pip3 install pyqt5—sip |
Теперь вы можете загрузить и установить исходник PyQt5.
Исходники
Скачать исходник PyQt5 можно отсюда: https://www.riverbankcomputing.com/software/pyqt/download5
Внимание: На момент прочтения статьи возможно появилась новая версия которая отличается от той что в скрине. Версия на текущий момент 5.11.3, вы должны самостоятельно скопировать ссылку с сайта и предоставить её в wget. Заметьте, что обновить версию придется во всех ниже предоставленных командах.
wget https://sourceforge.net/projects/pyqt/files/PyQt5/PyQt—5.11.3/PyQt5_gpl—5.11.3.tar.gz tar —xvzf PyQt5_gpl—5.11.3.tar.gz cd PyQt5_gpl—5.11.3 |
Мы распаковали сжатый исходник, теперь запустите следующие команды внутри корня папки:
sudo python3 configure.py sudo make sudo make install |
Чтобы убедиться в том, что все прошло гладко, попробуйте импортировать модуль PyQt5 так же, как мы делали все раньше. Все должно пройти хорошо.
Установка PyQt5 из исходников на Windows
Скачивайте и распакуйте архив с сайта которого мы указали выше.
Так как SIP требует компилятор GCC, вам нужно установить MinGW, который является портом Windows для компилятора Linux, GCC.
Единственное, что нужно поменять — это момент конфигурации. Вам нужно сообщить Python о платформе.
Это можно выполнить следующим образом:
python configure.py —platform win32—g++ make make install |
Поздравляем! Вы успешно установили PyQt5 из исходника.
Установка PyQt5 Designer
Есть два способа создания GUI приложений при помощи PyQt5:
- Дизайн виджетов при помощи кода;
- Использование PyQt5 Designer.
В этом руководстве мы используем PyQt5 Designer, который упрощает процесс на столько, что вы можете выполнить большой объем работы за секунды.
Недорого заказать услуги SMM продвижения более чем в 9 социальных сетях можно на https://doctorsmm.com/. С помощью этого сервиса можно раскрутить свою группу, страницу, сообщество или канал и набрать нужное количество подписчиков, лайков, репостов и других соцсигналов.
Дизайнер PyQt5 поставляется вместе с набором инструментов. Для его установки, вам нужно установить эти инструменты.
$ pip3 install pyqt5—tools |
Где находится дизайнер PyQt5?
После удачной установки, вы можете найти дизайнер PyQt5 здесь:
C:Program FilesPython36Libsite—packagespyqt5—tools |
Кстати, если вы установили только для своего текущего пользовательского аккаунта, вы найдете дизайнер PyQt5 вот здесь:
C:UsersPythonUserAppDataLocalProgramsPythonPython36—32Libsite—packages pyqt5—tools |
Вы можете создать короткий путь для него, вместо того, чтобы постоянно переходить к этому расположению для запуска дизайнера PyQt5.
Как использовать дизайнер PyQt5
Откройте designer.exe и увидите диалоговое окно, спрашивающее о том, какую форму шаблона вы предпочитаете.
Существует пять видов доступных шаблонов:
- Диалоговое окно с кнопками внизу (Dialog with Buttons Bottom): создает форму с кнопками ОК и Cancel в правом нижнем углу формы.
- Диалоговое окно с кнопками справа (Dialog with Buttons Right): создает форму с кнопками OK и Cancel в верхнем правом углу формы.
- Диалоговое окно без кнопок (Dialog without Buttons): создает пустую форму;
- Главное окно (Main Window): создает окно с панелью меню и набором инструментов. Унаследовано из QmainWindow;
- Виджет (Widget): создает виджет, наследуемый из класса Qwidget. Отличается от диалоговых шаблонов тем, что они наследуются из класса QВialog
Итак, у нас есть три типа шаблонов. В чем между ними разница?
Разница между QDialog, QMainWindow, и Qwidget
- QWidget – это базовый класс для всех GUI Элементов в PyQt5;
- QDialog используется при запросе чего-либо у пользователя, например, запросы о принятии или отклонении чего-нибудь. Основан на Qwidget.
- QMainWindow – самый большой шаблон, где вы можете разместить вашу панель инструментов, меню, статус и другие виджеты. Не имеет встроенных кнопок разрешения, таких как в QDialog.
Загрузка .ui против конвертации .ui в .py
В данном руководстве мы используем PyQt5 Designer, но перед тем, как мы пойдем дальше, давайте рассмотрим, как еще мы можем использовать сгенерированный файл из PyQt5 Designer.
Нам нужно открыть PyQt5 Designer, выбрать шаблон Main Window и нажать кнопку create.
Далее в файловом меню (File), нажимаем сохранить. PyQt5 Designer экспортирует вашу форму в XML с расширением .ui.
Для использования этого дизайна, у вас есть два способа:
- Загрузить файл .ui в ваш код Python;
- Конвертировать файл .ui в файл .py при помощи pyuic5;
Загрузка .ui файла в ваш код Python
Чтобы загрузить файл .ui в ваш код Python, вы можете использовать функцию loadUI() из uic вот так:
from PyQt5 import QtWidgets, uic import sys app = QtWidgets.QApplication([]) win = uic.loadUi(«mydesign.ui») # расположение вашего файла .ui win.show() sys.exit(app.exec()) |
Если вы запустите код, вы увидите окно, в котором есть только ярлык.
Это значит, что ui файл успешно загрузился!
Мы используем sys.exit(app.exec()) вместо использования app.exec() напрямую, чтобы выслать правильный код статуса, родительский процесс, или процесс вызова.
Если вы использовали app.exec() напрямую, приложение отправит ноль, что говорит об успехе, и это произойдет даже если приложение упадет.
Конвертация файла .ui в файл .py при помощи pyuic5
Давайте попробуем еще один способ и конвертируем файл .ui в код Python:
$ pyuic5 mydesign.ui —o mydesign.py |
Да! Был создан новый файл под названием mydesign.py. Теперь, импортируем этот файл, чтобы показать его в окне.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
from PyQt5 import QtWidgets from mydesign import Ui_MainWindow # импорт нашего сгенерированного файла import sys class mywindow(QtWidgets.QMainWindow): def __init__(self): super(mywindow, self).__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) app = QtWidgets.QApplication([]) application = mywindow() application.show() sys.exit(app.exec()) |
Если запустите этот код, вы должны увидеть то же окно, что было в первом методе.
Преимущество использования второго метода — это автоматическое завершение, которое выполнит IDE, так как все ваши виджеты импортированы. В то же время, пользуясь первым методом, вы просто загружаете файл .ui и вам нужно обращать внимание на названия ваших виджетов.
Еще одно преимущество использования второго метода. Скорость: вам не нужен парсинг XML для загрузки UI.
Так что мы можем сказать, что конвертация файла .ui в файл .py – безопаснее для кодинга и быстрее для загрузки.
Настало время закатить рукава и поиграть с виджетами PyQt5.
Для внесение виджета QLabel в вашу форму, выполните следующее:
- Откройте PyQt5 Designer и выберите шаблон Main Window;
- Перетяните виджет ярлыка из бокса слева;
Сохраните дизайн в файл как qlabel.ui и конвертируйте его в файл qlabel.py. Теперь поработаем с ярлыком виджета при помощи кода.
pyuic5 qlabel.ui —o qlabel.py |
Результат:
Меняем шрифт QLabel
Чтобы поменять шрифт QLabel, используйте метод setFont() и передайте ему QFont следующим образом:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
from PyQt5 import QtWidgets, QtGui from mydesign import Ui_MainWindow import sys class mywindow(QtWidgets.QMainWindow): def __init__(self): super(mywindow, self).__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) self.ui.label.setFont( QtGui.QFont(‘SansSerif’, 30) ) # Изменение шрифта и размера app = QtWidgets.QApplication([]) application = mywindow() application.show() sys.exit(app.exec()) |
После того, как запустите этот код, обратите внимание на то, что ярлык возникает некорректно, так как размер — меньше, чем размер шрифта, который мы используем. Так что нам нужно установить размер ярлыка.
Меняем размер QLabel
Чтобы поменять размер QLabel, вам нужно указать его геометрию при помощи метода setGeometry(), вот так:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
from PyQt5 import QtWidgets, QtGui,QtCore from mydesign import Ui_MainWindow import sys class mywindow(QtWidgets.QMainWindow): def __init__(self): super(mywindow, self).__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) self.ui.label.setFont( QtGui.QFont(‘SansSerif’, 30) ) self.ui.label.setGeometry( QtCore.QRect(10, 10, 200, 200) ) # изменить геометрию ярлыка app = QtWidgets.QApplication([]) application = mywindow() application.show() sys.exit(app.exec()) |
Меняем текст в QLabel
Чтобы изменить текст в QLabel, вы можете использовать метод setText(), вот так:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
from PyQt5 import QtWidgets, QtGui,QtCore from qlabel import Ui_MainWindow import sys class mywindow(QtWidgets.QMainWindow): def __init__(self): super(mywindow, self).__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) self.ui.label.setFont( QtGui.QFont(‘SansSerif’, 30) ) self.ui.label.setGeometry( QtCore.QRect(10, 10, 200, 200) ) self.ui.label.setText(«PyScripts») # Меняем текст app = QtWidgets.QApplication([]) application = mywindow() application.show() sys.exit(app.exec()) |
Именно на столько все просто! Давайте рассмотрим другие виджеты.
Виджет QLineEdit – это редактируемое поле, где вы можете принимать данные от пользователя. LineEdit содержит множество методов, с которыми можно работать.
Я создам новый дизайн qline.ui, используя дизайнер PyQt5 и внесу шесть виджетов QLineEdit и экспортирую его в файл qline.py.
pyuic5 qline.ui —o qline.py |
Cодержимое файла qline.py после конвертации:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
# -*- coding: utf-8 -*- # Form implementation generated from reading ui file ‘qline.ui’ # # Created by: PyQt5 UI code generator 5.11.3 # # WARNING! All changes made in this file will be lost! from PyQt5 import QtCore, QtGui, QtWidgets class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName(«MainWindow») MainWindow.resize(785, 600) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName(«centralwidget») self.lineEdit = QtWidgets.QLineEdit(self.centralwidget) self.lineEdit.setGeometry(QtCore.QRect(10, 10, 291, 31)) self.lineEdit.setObjectName(«lineEdit») self.lineEdit_2 = QtWidgets.QLineEdit(self.centralwidget) self.lineEdit_2.setGeometry(QtCore.QRect(10, 50, 291, 31)) self.lineEdit_2.setObjectName(«lineEdit_2») self.lineEdit_3 = QtWidgets.QLineEdit(self.centralwidget) self.lineEdit_3.setGeometry(QtCore.QRect(10, 90, 291, 31)) self.lineEdit_3.setObjectName(«lineEdit_3») self.lineEdit_4 = QtWidgets.QLineEdit(self.centralwidget) self.lineEdit_4.setGeometry(QtCore.QRect(10, 130, 291, 31)) self.lineEdit_4.setObjectName(«lineEdit_4») self.lineEdit_5 = QtWidgets.QLineEdit(self.centralwidget) self.lineEdit_5.setGeometry(QtCore.QRect(10, 170, 291, 31)) self.lineEdit_5.setObjectName(«lineEdit_5») self.lineEdit_6 = QtWidgets.QLineEdit(self.centralwidget) self.lineEdit_6.setGeometry(QtCore.QRect(10, 210, 291, 31)) self.lineEdit_6.setObjectName(«lineEdit_6») MainWindow.setCentralWidget(self.centralwidget) self.menubar = QtWidgets.QMenuBar(MainWindow) self.menubar.setGeometry(QtCore.QRect(0, 0, 785, 25)) self.menubar.setObjectName(«menubar») MainWindow.setMenuBar(self.menubar) self.statusbar = QtWidgets.QStatusBar(MainWindow) self.statusbar.setObjectName(«statusbar») MainWindow.setStatusBar(self.statusbar) self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate(«MainWindow», «MainWindow»)) |
Давайте познакомимся с методами QLineEdit:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
from PyQt5 import QtWidgets, QtCore # Импортируем наш файл from qline import Ui_MainWindow import sys class mywindow(QtWidgets.QMainWindow): def __init__(self): super(mywindow, self).__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) # Меняем текст self.ui.lineEdit.setText(«Добро пожаловать на PythonScripts») # указать максимальную длину self.ui.lineEdit_2.setMaxLength(10) # ввод пароля self.ui.lineEdit_3.setEchoMode(QtWidgets.QLineEdit.Password) # только чтение без изменения содержимого. self.ui.lineEdit_4.setReadOnly(True) # меняем цвет вводимого текста self.ui.lineEdit_5.setStyleSheet(«color: rgb(28, 43, 255);») # изменение цвета фона QLineEdit self.ui.lineEdit_6.setStyleSheet(«background-color: rgb(28, 43, 255);») app = QtWidgets.QApplication([]) application = mywindow() application.show() sys.exit(app.exec()) |
Результат:
- Для 1-го QLineEdit, мы изменили текст, при помощи метода setText().
- Для 2-го QLineEdit, мы установили максимум доступных 10-и символов, так что более 10-и приниматься не будут.
- Для 3-го QLineEdit, мы установили режим пароля, так ваши введенные данные отображаются как звездочки;
- Для 4-го QLineEdit, мы установили режим «только для чтения», так что редактировать контент не представляется возможным.
- Для 5-го QLineEdit мы изменили цвет шрифта при помощи метода setStyleSheet() и указали нужный цвет с помощью CSS (как и для обычной веб страницы).
- Для 6-го QLineEdit мы изменили цвет фона при помощи метода setStyleSheet() и CSS.
Метод setStyleSheet()
Метод setStyleSheet() может быть использован с виджетами PyQt5 для изменения стилей.
Вы можете изменить следующие параметры, пользуясь методом setStyleSheet():
- Размер и тип шрифта;
- Цвет текста;
- Цвет заднего фона;
- Цвет верхней границы;
- Цвет нижней границы;
- Цвет левой границы;
- Цвет правой границы;
- Цвет выделения;
- Цвет выделения заднего фона.
Это наиболее важные значения, которые можно передать методу setStyleSheet().
Большая часть ваших программ Python будут содержать виджет QPushButton. Вы нажимаете кнопку, и какой-нибудь код выполняется.
Если у вас имеется опыт в программировании, вы могли слышать об обработке событий, где вы взаимодействуете с виджетом и функция выполняется.
Суть идеи сохранилась такой же и в PyQt5, только определения немного отличаются.
Событие клика в PyQt5 называется сигналом, и метод, который будет выполняться, называется слот.
Так что при нажатии на QPushButton, сигнал издается. Названием сигнала в данном случае, является clicked().
Чтобы связать сигнал со слотом, вам нужно использовать метод connect(), что вы сейчас и увидите.
Этот процесс обработки события продолжает работать до тех пор, пока вы не закроете вашу форму, или главный виджет.
Давайте создадим форму myform.ui при помощи QLabel и QPushButton и экспортируем её в файл myform.py.
Экспортируем myform.ui в myform.py
pyuic5 myform.ui —o myform.py |
Сейчас, мы подключим сигнал clicked() к слоту при помощи метода connect(), вот так:
self.ui.pushButton.clicked.connect(self.btnClicked) |
Здесь, btnClicked – это слот, или функция, которая будет выполнена после того, как вы кликните на QPushButton.
Итак, ваш код будет выглядеть следующим образом:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
from PyQt5 import QtWidgets # Импортируем наш шаблон. from myform import Ui_MainWindow import sys class mywindow(QtWidgets.QMainWindow): def __init__(self): super(mywindow, self).__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) # подключение клик-сигнал к слоту btnClicked self.ui.pushButton.clicked.connect(self.btnClicked) def btnClicked(self): self.ui.label.setText(«Вы нажали на кнопку!») # Если не использовать, то часть текста исчезнет. self.ui.label.adjustSize() app = QtWidgets.QApplication([]) application = mywindow() application.show() sys.exit(app.exec()) |
Результат:
Замечательно!
Визуальный редактор слота/сигнала
Мы видели, как подключать сигнал виджета к слоту при помощи метода connect(), но это не единственный способ.
На самом деле, для каждого виджета есть предопределенные слоты. Вы можете связать сигнал с любым предопределенным слотом, без необходимости кодить в дизайнере PyQt5.
Перетяните QPushButton и QLineEdit в вашу форму.
Нажмите F4 и перетяните курсор из QPushButton и отпустите его в верхней части QLineEdit. Чтобы вернуться в обычный режим, нажмите на F3.
Благодаря этому появится редактор сигнала/слота.
Слева находятся предопределенные сигналы, справа — предопределенные слоты. Скажем, нам нужно подключить сигнал clicked() с слотом «очистки содержимого«.
Выберите сигнал clicked слева и выберите clear слот справа и нажмите OK.
После выполнения подключений ваших сигналов и слотов, вы можете выйти из этого режима, нажав ESC, или F3.
Сейчас, если вы запустите эту форму, и нажмете QPushButton, то любой текст в QLineEdit будет очищен. Вы можете редактировать или удалять эти связи в панели редактора сигналов и слотов.
Сохраните форму как signaledit.ui и конвертируем её в signaledit.py:
pyuic5 signaledit.ui —o signaledit.py |
Полученный файл импортируем в наш код:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
from PyQt5 import QtWidgets # Импортируем наш шаблон. from signaledit import Ui_MainWindow import sys class mywindow(QtWidgets.QMainWindow): def __init__(self): super(mywindow, self).__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) app = QtWidgets.QApplication([]) application = mywindow() application.show() sys.exit(app.exec()) |
Результат:
Как выпускать сигналы в PyQt5
Мы увидели, как работают сигналы и слоты. Все сигналы, с которыми мы работали, являются предопределенными для нас.
Но что на счет выпуска собственного сигнала?
Это очень просто! Вы можете сделать это, просто использовав класс pyqtSignal, как показано ниже:
- Определите ваше событие типом pyqtSignal;
- Вызовите метод emit() в том месте, где вы хотите, чтобы произошло событие.
Скажем, у нас есть класс nut, и мы хотим, чтобы сигнал cracked был выпущен.
from PyQt5.QtCore import pyqtSignal, QObject class nut(QObject): cracked = pyqtSignal() def __init__(self): QObject.__init__(self) def crack(self): self.cracked.emit() |
Как использовать сигнал
Сейчас мы сделаем наш пример более практичным, создаем экземпляр класса nut и выпуская сигнал cracked:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
from PyQt5.QtCore import pyqtSignal, QObject class nut(QObject): cracked = pyqtSignal() def __init__(self): QObject.__init__(self) def crack(self): self.cracked.emit() def crackit(): print(«hazelnut cracked!») hazelnut = nut() # подключение сигнала cracked к слоту crackit hazelnut.cracked.connect(crackit) hazelnut.crack() |
Сигнал cracked успешно выпущен.
Переопределение сигнала (события) в PyQt5
Иногда нам может понадобиться переопределить поведение по умолчанию для особенных событий или сигналов.
Давайте рассмотрим практичный пример для этого случая. Если вы хотите закрыть окно, когда пользователь нажимает на определенную клавишу, вы можете переопределить keyPressEvent внутри вашего главного окна следующим образом:
def keyPressEvent(self, e): if e.key() == Qt.Key_F12: self.close() |
Теперь, если пользователь нажмет клавишу F12, главное окно будет закрыто.
Здесь мы переопределили основной сигнал нажатия в главном окне и закрыли это окно.
Вместо того, чтобы разрешить пользователю вводить свои данные в QLineEdit, или любом другом редактируемом виджете, мы можем использовать виджет QCombobBox, чтобы дать список данных, из которого он сможет выбирать.
Давайте перетянем QComboBox в нашу форму и взглянем на её методы.
Сохраняем файл как combobox.ui и конвертируем его в combobox.py:
pyuic5 combobox.ui —o combobox.py |
Если вы запустите приложение сейчас, обратите внимание на то, что QComboBox — пустой. Чтобы вносить объекты в QComboBox, используйте метод addItem():
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
from PyQt5 import QtWidgets from combobox import Ui_MainWindow import sys class mywindow(QtWidgets.QMainWindow): def __init__(self): super(mywindow, self).__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) # Добавляем новые значения self.ui.comboBox.addItem(«Программист») self.ui.comboBox.addItem(«Дизайнер») app = QtWidgets.QApplication([]) application = mywindow() application.show() sys.exit(app.exec()) |
Получаем все элементы из QComboBox
Нет прямого способа получить все значения из QComboBox, но вы можете применить цикл Python для этой цели. Для этого подойдет функция range.
for i in range(self.ui.comboBox.count()): print(self.ui.comboBox.itemText(i)) |
Выбор одного элемента из QCombobox
Чтобы выбрать элемент из QComboBox, у вас есть два метода:
# по индексу, который начинается с нуля self.ui.comboBox.setCurrentIndex(1) #выбор по тексту self.ui.comboBox.setCurrentText(«Second item») |
Обратите внимание на то, что при выборе элемента по тексту, следует убедиться в том, что вы вводите правильный текст. В противном случае, QComboBox останется на первом элементе.
Если вы хотите просмотреть вашу базу данных в формате таблицы, в PyQt5 предоставляется QTableWidget как раз для этой цели.
QTableWidget состоит из клеток, каждая клетка — экземпляр класса QTableWidgetItem.
Давайте создадим форму, которая содержит QTableWidget и QPushButton.
Перетяните QTableWidget и QPushButton из PyQt5 Designer. После этого, сохраните форму как qtable.ui и конвертируйте дизайн в qtable.py.
pyuic5 qtable.ui —o qtable.py |
Чтобы добавлять ряды в QTableWidget, вы можете использовать метод setRowCount().
Для внесения столбцов в QTableWidget, воспользуйтесь методом setColumnCount().
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
from PyQt5 import QtWidgets # Импортируем нашу форму. from qtable import Ui_MainWindow import sys class mywindow(QtWidgets.QMainWindow): def __init__(self): super(mywindow, self).__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) self.ui.tableWidget.setColumnCount(2) self.ui.tableWidget.setRowCount(4) app = QtWidgets.QApplication([]) application = mywindow() application.show() sys.exit(app.exec()) |
Теперь вы можете писать текст вручную внутри клеток QTableWidget.
Очистка содержимого QTableWidget
Чтобы очистить содержимое QTableWidget, вы можете использовать метод clear, вот так:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
from PyQt5 import QtWidgets # Импортируем нашу форму. from qtable import Ui_MainWindow import sys class mywindow(QtWidgets.QMainWindow): def __init__(self): super(mywindow, self).__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) self.ui.tableWidget.setColumnCount(2) self.ui.tableWidget.setRowCount(4) # очистка таблицы при клике на кнопку. self.ui.pushButton.clicked.connect(self.clear) def clear(self): self.ui.tableWidget.clear() app = QtWidgets.QApplication([]) application = mywindow() application.show() sys.exit(app.exec()) |
Заполнение QTableWidget из кода
Чтобы заполнить QtableWidget программно, вам нужно использовать метод setItem() для каждого объекта QtableWidgetItem.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
from PyQt5.QtWidgets import QTableWidgetItem from qtable import * import sys data = [] data.append((‘Заполнить’, ‘QTableWidget’)) data.append((‘с данными’, ‘в Python’)) data.append((‘очень’, ‘просто’)) class mywindow(QtWidgets.QMainWindow): def __init__(self): super().__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) self.ui.tableWidget.setRowCount(3) self.ui.tableWidget.setColumnCount(2) # очистка таблицы при клике на кнопку. self.ui.pushButton.clicked.connect(self.clear) row = 0 for tup in data: col = 0 for item in tup: cellinfo = QTableWidgetItem(item) self.ui.tableWidget.setItem(row, col, cellinfo) col += 1 row += 1 def clear(self): self.ui.tableWidget.clear() app = QtWidgets.QApplication([]) win = mywindow() win.show() sys.exit(app.exec()) |
- Сначала мы создали список трех кортежей Python;
- Внутри конструктора главного окна, мы установили количество столбцов и рядов;
- Далее мы перебираем список и получаем каждый кортеж в списке, для заполнения клеток таблицы, при помощи метода setItem()
- Наконец, мы показываем главное окно.
Делаем QTableWidget нередактируемым (только для чтения)
Вам может не понравится то, что клетки в вашей таблице могут быть отредактированы пользователем в том или ином случае. Например, при отображении нередактируемых данных. В этом случае возможность редактирования не имеет никакого смысла.
Чтобы сделать QTableWidget нередактируемым, вы можете использовать метод setFlags(), чтобы сделать каждый QTableWidgetItem доступным только для чтения.
# Только для чтения cellinfo.setFlags( QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled ) |
Вам нужно установить флажки, перед тем как настраивать содержимое вашей клетки.
Таким образом, ваш код будет выглядеть вот так:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
from PyQt5.QtWidgets import QTableWidgetItem from qtable import * import sys data = [] data.append((‘Заполнить’, ‘QTableWidget’)) data.append((‘с данными’, ‘в Python’)) data.append((‘очень’, ‘просто’)) class mywindow(QtWidgets.QMainWindow): def __init__(self): super().__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) self.ui.tableWidget.setRowCount(3) self.ui.tableWidget.setColumnCount(2) # очистка таблицы при клике на кнопку. self.ui.pushButton.clicked.connect(self.clear) row = 0 for tup in data: col = 0 for item in tup: cellinfo = QTableWidgetItem(item) # Только для чтения cellinfo.setFlags( QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled ) self.ui.tableWidget.setItem(row, col, cellinfo) col += 1 row += 1 def clear(self): self.ui.tableWidget.clear() app = QtWidgets.QApplication([]) win = mywindow() win.show() sys.exit(app.exec()) |
Теперь, если вы попробуете отредактировать какую-либо клетку — у вас не выйдет, так как QtableWidgetItem теперь нельзя редактировать
До этого момента, названия столбцов QTableWidget были числами. Как на счет того, чтобы поменять названия столбцов на что-нибудь другое?
Чтобы задать текст заголовкам QTableWidget, вы можете использовать метод setHorizontalHeaderLabels(), вот так:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
from PyQt5.QtWidgets import QTableWidgetItem from qtable import * import sys data = [] data.append((‘BMW’, ‘1991’)) data.append((‘Audi’, ‘2003’)) data.append((‘Volvo’, ‘2010’)) class mywindow(QtWidgets.QMainWindow): def __init__(self): super().__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) self.ui.tableWidget.setRowCount(3) self.ui.tableWidget.setColumnCount(2) # очистка таблицы при клике на кнопку. self.ui.pushButton.clicked.connect(self.clear) # заголовки для столбцов. self.ui.tableWidget.setHorizontalHeaderLabels( (‘Марка’, ‘Год выпуска’) ) row = 0 for tup in data: col = 0 for item in tup: cellinfo = QTableWidgetItem(item) self.ui.tableWidget.setItem(row, col, cellinfo) col += 1 row += 1 def clear(self): self.ui.tableWidget.clear() app = QtWidgets.QApplication([]) win = mywindow() win.show() sys.exit(app.exec()) |
Таким же образом, вы можете менять заголовок ряда, при помощи метода setVerticalHeaderLabels():
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
from PyQt5.QtWidgets import QTableWidgetItem from qtable import * import sys data = [] data.append((‘BMW’, ‘1991’)) data.append((‘Audi’, ‘2003’)) data.append((‘Volvo’, ‘2010’)) class mywindow(QtWidgets.QMainWindow): def __init__(self): super().__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) self.ui.tableWidget.setRowCount(3) self.ui.tableWidget.setColumnCount(2) # очистка таблицы при клике на кнопку. self.ui.pushButton.clicked.connect(self.clear) # заголовки для столбцов. self.ui.tableWidget.setHorizontalHeaderLabels( (‘Марка’, ‘Год выпуска’) ) # названия рядов. self.ui.tableWidget.setVerticalHeaderLabels( (‘900$’, ‘5000$’, ‘13000$’) ) row = 0 for tup in data: col = 0 for item in tup: cellinfo = QTableWidgetItem(item) self.ui.tableWidget.setItem(row, col, cellinfo) col += 1 row += 1 def clear(self): self.ui.tableWidget.clear() app = QtWidgets.QApplication([]) win = mywindow() win.show() sys.exit(app.exec()) |
Как сортировать QTableWidget
Вы можете сделать ваш QTableWidget сортируемым, при помощи метода setSortingEnabled().
self.ui.tableWidget.setSortingEnabled(True) |
Теперь, если пользователь нажмет на любой заголовок столбца, он может сортировать данные в порядке убывания, или возрастания.
Вы можете использовать этот метод перед, или до наполнения QTableWidget данными.
Что на счет сортировки в QTableWidget, но только для определенного столбца?
Вы можете использовать метод sortByColumn(), и указать индекс столбца и порядок сортировки, вот так:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
from PyQt5.QtWidgets import QTableWidgetItem from qtable import * import sys data = [] data.append((‘BMW’, ‘2005’)) data.append((‘Audi’, ‘2003’)) data.append((‘Volvo’, ‘1990’)) data.append((‘Toyota’, ‘2018’)) class mywindow(QtWidgets.QMainWindow): def __init__(self): super().__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) # Кол-во рядов меняется в зависимости от значений в data. self.ui.tableWidget.setRowCount( len(data) ) # Кол-во столбцов меняется в зависимости от data. self.ui.tableWidget.setColumnCount( len(data[0]) ) # очистка таблицы при клике на кнопку. self.ui.pushButton.clicked.connect(self.clear) # заголовки для столбцов. self.ui.tableWidget.setHorizontalHeaderLabels( (‘Марка’, ‘Год выпуска’) ) row = 0 for tup in data: col = 0 for item in tup: cellinfo = QTableWidgetItem(item) self.ui.tableWidget.setItem(row, col, cellinfo) col += 1 row += 1 # Сортировка по году выпуска. # 0 — Марка # 1 — Год выпуска self.ui.tableWidget.sortByColumn( 1, QtCore.Qt.AscendingOrder ) def clear(self): self.ui.tableWidget.clear() app = QtWidgets.QApplication([]) win = mywindow() win.show() sys.exit(app.exec()) |
Кстати, вы можете использовать метод sortItems() для сортировки QTableWidget в возрастающем порядке по умолчанию.
self.ui.tableWidget.sortItems(0) |
Или вы можете определить свой порядок сортировки:
self.ui.tableWidget.sortItems(1, QtCore.Qt.DescendingOrder) |
Помните, что если вы хотите сортировать ваши столбцы программно, вам нужно использовать методы сортировки после заполнения QTableWidget данными, иначе они не будут в нужном вам порядке.
Добавляем QComboBox в QTableWidget
У вас может появится задача, чтобы пользователь выбирал значение внутри QTableWidget, вместо ввода текста.
Как на счет того, чтобы добавить QComboBox в QTableWidgetItem?
Чтобы добавить QComboBox внутрь QTableWidgetItem, вы можете использовать метод setCellWidget():
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
from PyQt5.QtWidgets import QTableWidgetItem from qtable import * import sys data = [‘Python’, ‘PHP’, ‘Java’] class mywindow(QtWidgets.QMainWindow): def __init__(self): super().__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) self.ui.tableWidget.setRowCount(3) self.ui.tableWidget.setColumnCount(2) row = 0 for item in data: cellinfo = QTableWidgetItem(item) combo = QtWidgets.QComboBox() combo.addItem(«Изучить») combo.addItem(«Забыть») combo.addItem(«Удалить») self.ui.tableWidget.setItem(row, 0, cellinfo) self.ui.tableWidget.setCellWidget(row, 1, combo) row += 1 app = QtWidgets.QApplication([]) win = mywindow() win.show() sys.exit(app.exec()) |
Отлично!
Не ограничивайте себя в воображении и попробуйте вставлять различные виджеты, такие как QСheckbox, или даже QProgressBar.
QProgressBar в QTableWidget
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
from PyQt5.QtWidgets import QTableWidgetItem from qtable import * import sys data = ( (‘Python’, 95.5), (‘PHP’, 55.1), (‘Java’, 0.29) ) class mywindow(QtWidgets.QMainWindow): def __init__(self): super().__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) self.ui.tableWidget.setRowCount(3) self.ui.tableWidget.setColumnCount(2) self.ui.tableWidget.setHorizontalHeaderLabels( (‘Язык’, ‘Знания’) ) line = 0 for item in data: cellinfo = QTableWidgetItem(item[0]) self.ui.tableWidget.setItem(line, 0, cellinfo) # Создаем QProgressBar progress = QtWidgets.QProgressBar() progress.setMinimum(0) progress.setMaximum(100) # Формат вывода: 10.50% progress.setValue(item[1]) progress.setFormat(‘{0:.2f}%’.format(item[1])) # Добавляем виджет в ячейку. self.ui.tableWidget.setCellWidget(line, 1, progress) line += 1 app = QtWidgets.QApplication([]) win = mywindow() win.show() sys.exit(app.exec()) |
Указанный выше код будет таким же, за исключением строки, где вы создаете QСomboBox, здесь вы внесете тот виджет, который вам нужен.
Единственное ограничение — это ваше собственное воображение!
Компиляция Python приложения
Вы можете конвертировать ваши программы Python в бинарные исполняемые, и для этого имеется множество инструментов.
Лично я предпочитаю pyinstaller, который подходит для упаковки кода Python в исполняемый файл под Windows, Mac OS X, Solaris, Linux и FreeBSD. Все это будет поддерживаться 32 и 64-битной архитектурой.
Лучшая в pyinstaller для нас — это наличие полной поддержки для PyQt5.
Отлично! Для начала, установим pyinstaller:
$ pip3 install pyinstaller |
После проведения установки, вы можете конвертировать программы Python следующим образом:
Ваш исполняемый файл будет создан в папке под названием dist в директории вашей программы Python.
Как вы могли догадаться, вместе с исполняемым файлом будет генерироваться множество зависимостей. Как сделать из этого один файл?
Вы можете создать один исполняемый файл. Вот так:
$ pyinstaller —onefile test.py |
Каждый раз, когда вы запускаете ваш исполняемый файл, будет возникать окно, как его спрятать?
Вы можете использовать флажки -w или –noconsole, чтобы спрятать окно консоли:
Эта опция доступна только для Windows и Mac OS X.
Pyinstaller предоставляет множество вариантов для упаковки вашего приложения, чтобы увидеть полный список, используйте –help:
Я старался сделать все на столько простым, на сколько это возможно. Надеюсь, это руководство оказалось для вас полезным.
Спасибо.
Являюсь администратором нескольких порталов по обучению языков программирования Python, Golang и Kotlin. В составе небольшой команды единомышленников, мы занимаемся популяризацией языков программирования на русскоязычную аудиторию. Большая часть статей была адаптирована нами на русский язык и распространяется бесплатно.
E-mail: vasile.buldumac@ati.utm.md
Образование
Universitatea Tehnică a Moldovei (utm.md)
- 2014 — 2018 Технический Университет Молдовы, ИТ-Инженер. Тема дипломной работы «Автоматизация покупки и продажи криптовалюты используя технический анализ»
- 2018 — 2020 Технический Университет Молдовы, Магистр, Магистерская диссертация «Идентификация человека в киберпространстве по фотографии лица»
Время на прочтение
3 мин
Количество просмотров 43K
Привет, Хабр! Сегодня я вас хочу научить делать интерфейс на Python 3&PyQt5.
Установка PyQt5
Для того, чтобы установить PyQt5 в Windows или MacOS, откройте Командную строку или Терминал и введите:
pip3 install PyQt5
Для Linux, откройте Терминал и введите:
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install python3-pyqt5
Hello, World!
А сейчас сделаем Hello World приложение. Создайте файл Python, откройте его и введите такой код:
from PyQt5.QtWidgets import *
import sys
class MainWindow(QMainWindow): # главное окно
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi()
def setupUi(self):
self.setWindowTitle("Hello, world") # заголовок окна
self.move(300, 300) # положение окна
self.resize(200, 200) # размер окна
self.lbl = QLabel('Hello, world!!!', self)
self.lbl.move(30, 30)
if __name__ == "__main__":
app = QApplication(sys.argv)
win = MainWindow()
win.show()
sys.exit(app.exec_())
Когда вы запустите, должна получится примерно такая картина:
Меняем шрифт надписи
А теперь поменяем шрифт надписи. Теперь код станет таким:
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
import sys
class MainWindow(QMainWindow): # главное окно
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi()
def setupUi(self):
self.setWindowTitle("Hello, world") # заголовок окна
self.move(300, 300) # положение окна
self.resize(200, 200) # размер окна
self.lbl = QLabel('Hello, world!!!', self)
self.lbl.move(30, 30)
self.font = QFont() # создаём объект шрифта
self.font.setFamily("Rubik") # название шрифта
self.font.setPointSize(12) # размер шрифта
self.font.setUnderline(True) # подчёркивание
self.lbl.setFont(self.font) # задаём шрифт метке
if __name__ == "__main__":
app = QApplication(sys.argv)
win = MainWindow()
win.show()
sys.exit(app.exec_())
Пример рассчитан на то, что у вас уже установлен шрифт Rubik от Google Fonts. Если нет, его всегда можно скачать отсюда.
Более продвинутая разметка с XHTML
А теперь добавим XHTML. Например, так:
from PyQt5.QtWidgets import *
import sys
class MainWindow(QMainWindow): # главное окно
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi()
def setupUi(self):
self.setWindowTitle("Hello, world") # заголовок окна
self.move(300, 300) # положение окна
self.resize(200, 200) # размер окна
self.lbl = QLabel('<i>Hello</i>, <b>world</b>!!! <s><b>123</b></s>', self)
self.lbl.move(30, 30)
if __name__ == "__main__":
app = QApplication(sys.argv)
win = MainWindow()
win.show()
sys.exit(app.exec_())
Те, кто хотя бы немного знают XHTML, заметят, что надпись Hello сделана курсивом, слово world — жирным, а 123 — и вычеркнуто, и жирное.
Шпаргалка по XHTML
<b>123</b> |
Жирный текст |
<i>123</i> |
Курив |
<u>123</u> |
Подчёркивание |
<s>123</s> |
Вычёркивание |
<code>123</code> |
Код (моноширным шрифтом) |
<sup>123</sup> |
Надстрочный текст |
<sub>123</sub> |
Подстрочный текст |
<span style=»font-size:16pt;»>123</span> |
Размер текста 16 пунктов |
<span style=»color:#cc0000;»>123</span> |
Красный текст |
<span style=» background-color:#00ff00;»>123</span> |
Текст на ярко-зелёном фоне. |
<span align=»center»>123</span> |
Выравнивание по центру |
Кстати, я знаю такой конструктор HTML. Лично мне он по душе. Только сложно вставлять свои тэги.
Больше надписей!
А теперь сделаем 2 надписи:
from PyQt5.QtWidgets import *
import sys
class MainWindow(QMainWindow): # главное окно
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi()
def setupUi(self):
self.setWindowTitle("Hello, world") # заголовок окна
self.move(300, 300) # положение окна
self.resize(200, 200) # размер окна
self.lbl = QLabel('<i>Hello</i>, <b>world</b>!!!', self)
self.lbl.move(30, 30)
self.lbl2 = QLabel('<u>Ещё одна метка</u>', self)
self.lbl2.move(50, 50)
if __name__ == "__main__":
app = QApplication(sys.argv)
win = MainWindow()
win.show()
sys.exit(app.exec_())
На вторую я тоже добавил форматирование (подчёркивание), а у первой убрал 123.
Окно без resize()
Все предыдущие примеры использовали такую конструкцию:
self.resize(200, 200)
Но без этой конструкции можно обойтись, так как виджеты будут сами себе расчищать место.
Подсказки
Ко всем виджетам можно добавить подсказку. Например (привожу только важную для понимания часть кода):
self.lbl.setToolTip('This is a <b>QLabel</b>')
Эпилог
Вот и всё. В следующей части я постараюсь описать кнопки, меню и события.
До новых встреч!
От автора: что такое PyQt? PyQt — это привязка Python с открытым исходным кодом для виджет-инструментария Qt, который также функционирует как кросс-платформенная среда разработки приложений. Qt — это популярная среда C ++ для написания приложений с помощью графического интерфейса для всех основных настольных, мобильных и встраиваемых платформ (поддерживает Linux, Windows, MacOS, Android, iOS, Raspberry Pi и многие другие).
PyQt разрабатывается и поддерживается Riverbank Computing, компанией, базирующейся в Англии, а Qt — финской фирмой The Qt Company.
В этом руководстве по PyQT мы рассмотрим:
Что такое PyQt?
Функции PyQT
Версии PyQt
Как установить PyQt
Основные понятия и программы PyQt
Компоненты и виджеты
Темы
Функци PyQT
PyQt состоит из более чем шести сотен классов, охватывающих ряд функций, таких как:
Графические пользовательские интерфейсы
Базы данных SQL
Веб-инструментарий
Обработка XML
Сети
Эти функции можно комбинировать для создания расширенных пользовательских интерфейсов, а также автономных приложений. Многие крупные компании из различных отраслей используют PyQt: LG, Mercedes, AMD, Panasonic, Harman и т. д.
Версии PyQt
PyQt доступен в двух редакциях: PyQt4 и PyQt5. PyQt4 предоставляет связующий код для привязки версий Qx 4.x и 5.x, в то время как PyQt5 обеспечивает привязку только для версий 5.x. В результате PyQt5 не имеет обратной совместимости с устаревшими модулями более ранней версии. В этом руководстве будет использоваться для демонстрации примеров PyQt5. Помимо этих двух версий, Riverbank Computing также предоставляет PyQt3D — привязки python для инфраструктуры Qt3D. Qt3D — это прикладная среда, используемая для создания систем моделирования в реальном времени с 2D / 3D рендерингом.
Как установить PyQt
Есть два способа установки PyQt.
Использование файлов Wheel
Сборка и установка из исходного кода
Qt (произносится «кьют») — сложная система, а база кода PyQt содержит скомпилированный код C ++ и Python. В результате по сравнению с другими библиотеками Python это сложный процесс для сборки и установки из исходного кода. Тем не менее, вы можете легко установить PyQt5 с помощью Wheel.
Установка с помощью Wheel
Wheel — это новый стандартный формат упаковки и распространения Python. Проще говоря, Wheel — это ZIP-архив со специальным названием и расширение файла. Wheel можно установить с помощью pip (менеджер пакетов Python), который включен по умолчанию в последние версии Python.
Итак, если у вас установлен Python 3.4 или более поздней версии, у вас уже есть pip. Однако, если вы используете более старую версию Python, вам нужно скачать и установить pip, прежде продолжать. Вы можете найти инструкции по установке по этой ссылке: //pypi.org/project/pip/.
Чтобы установить PyQt5:
Шаг 1) Откройте командную строку или PowerShell на компьютере с Windows.
Шаг 2) Введите следующее:
Этот шаг загрузит пакет PyQt5 whl (около 50 МБ) и установит его в вашей системе.
Кроме того, вы также можете загрузить двоичный файл Windows для версии Python, установленной на вашем компьютере. После завершения перейдите к следующему разделу, чтобы написать свое первое приложение с помощью графического интерфейса.
Основные понятия и программы PyQt
Теперь, когда вы успешно установили PyQt5 на компьютер, вы готовы писать приложения на python с помощью графического интерфейса. Давайте начнем с простого приложения, которое будет отображать пустое окно на экране. Запустите Python IDLE и введите следующее:
import sys from PyQt5.QtWidgets import QApplication, QWidget if __name__ == «__main__»: app = QApplication(sys.argv) w = QWidget() w.resize(300,300) w.setWindowTitle(‘Guru99’) w.show() sys.exit(app.exec_()) |
Сохраните его как app.py (имя не имеет значения) и нажмите F5, чтобы запустить программу. Или просто дважды кликните на сохраненном файле, чтобы запустить приложение. Если вы все сделали правильно, откроется новое окно с заголовком Guru99, как показано ниже.
Здорово! Работает. Это не так много, но достаточно, чтобы понять основы. Теперь давайте рассмотрим подробно, что делает каждая из строк в программе.
from PyQt5.QtWidgets import QApplication, QWidget |
Этот оператор импортирует все модули, необходимые для создания GUI, в текущее пространство имен. Модуль QtWidgets содержит все основные виджеты, которые вы будете использовать в этом руководстве.
app = QApplication(sys.argv) |
Здесь вы создаете объект класса QApplication. Этот шаг необходим для PyQt5; каждое приложение пользовательского интерфейса должно создавать экземпляр QApplication в качестве своего рода точки входа в приложение. Если вы не создадите его, будут выданы ошибки.
sys.argv — это список параметров командной строки, которые вы можете передать приложению при запуске через оболочку или при автоматизации интерфейса.
В этом примере вы не передали аргументы QApplications. Следовательно, вы также можете заменить его приведенным ниже кодом и даже не импортировать модуль sys.
app = QApplication([]) w = QWidget() |
Далее мы создаем объект класса QWidget. QWidget является базовым классом всех объектов пользовательского интерфейса в Qt, и практически все, что вы видите в приложении, является виджетом. Это включает в себя диалоговые окна, тексты, кнопки, панели и так далее. Функция, которая позволяет проектировать сложные пользовательские интерфейсы, основывается на том, что виджеты могут быть вложенными, то есть вы можете иметь виджет внутри виджета, который находится внутри еще одного виджета. Вы увидите это в действии в следующем разделе.
Метод resize класса QWidget позволяет устанавливать размеры любого виджета. В этом случае вы изменили размер окна на 300 * 300 пикселей. Здесь вы должны помнить, что виджеты могут быть вложены вместе, внешний виджет (т. е. виджет без родителя) называется окном.
w.setWindowTitle(‘Guru99’) |
Метод setWindowTitle () позволяет передать строку в качестве аргумента, который установит заголовок окна переданной вами строке. В этом примере в строке заголовка будет отображаться Guru99.
show() просто отображает виджет на экране монитора.
Метод app.exec_() запускает цикл событий Qt / C ++. Как вы знаете, PyQt в основном написан на C ++ и использует механизм цикла событий для реализации параллельного выполнения. app.exec_() передает управление Qt, который выходит из приложения только тогда, когда пользователь закроет его графический интерфейс. Вот почему Ctrl + C не выполняет выход из приложения, как в других программах Python. Поскольку Qt контролирует приложение, события Python не обрабатываются, пока мы не настроим их внутри приложения. Также обратите внимание, что у метода exec есть подчеркивание в имени; это потому, что exec() уже является ключевым словом в python, а подчеркивание разрешает конфликт имен.
Заполнение окон
В предыдущем разделе мы рассмотрели, как в Qt создать базовый виджет. Теперь пришло время сделать несколько более сложных интерфейсов, с которыми пользователи могут по-настоящему взаимодействовать. Снова, запустите IDLE и напишите следующее.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
import sys from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QPushButton, QMessageBox def dialog(): mbox = QMessageBox() mbox.setText(«Your allegiance has been noted») mbox.setDetailedText(«You are now a disciple and subject of the all-knowing Guru») mbox.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel) mbox.exec_() if __name__ == «__main__»: app = QApplication(sys.argv) w = QWidget() w.resize(300,300) w.setWindowTitle(‘Guru99’) label = QLabel(w) label.setText(«Behold the Guru, Guru99») label.move(100,130) label.show() btn = QPushButton(w) btn.setText(‘Beheld’) btn.move(110,150) btn.show() btn.clicked.connect(dialog) w.show() sys.exit(app.exec_()) |
Сохраните файл как appone.py или как угодно и нажмите F5, чтобы запустить программу. Если вы не допустили ошибок, IDLE откроет новое окно с текстом и кнопкой, как показано ниже.
Как только вы нажмете кнопку в первом окне, откроется новое окно сообщения с текстом, который вы написали. Теперь вы можете нажать кнопку Hide Details/Show Details, чтобы переключить видимость дополнительного текста.
Как вы можете видеть, поскольку мы не установили заголовок окна текста, заголовок по умолчанию был предоставлен самим python. Теперь, когда это работает, давайте взглянем на дополнительный код, который вы добавили в предыдущий пример.
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QPushButton, QMessageBox |
Это импортирует еще несколько виджетов, которые вы использовали в этом примере, а именно QLabel, QPushButton и QMessageBox.
def dialog(): mbox = QMessageBox() mbox.setText(«Your allegiance has been noted») mbox.setDetailedText(«You are now a disciple and subject of the all-knowing Guru») mbox.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel) mbox.exec_() |
Здесь вы определили метод с именем dialog, который создает виджет окна сообщения и устанавливает некоторый текст для кнопок и других полей.
Метод dialog вызывается из основного блока программы, когда кнопка нажимается в определенном виджете (в данном случае, btn PushButton). Событие клика, запущенное этой кнопкой, вызывает выполнение этой функции. Такая функция называется в Qt слотом, вы узнаете больше о сигналах и слотах в следующих разделах.
if __name__ == «__main__»: app = QApplication(sys.argv) w = QWidget() w.resize(300,300) w.setWindowTitle(‘Guru99’) |
Это основной раздел приложения, и, как и в предыдущем примере, вы начинаете с создания экземпляра QApplication, за которым следует простой виджет, это экземпляр QWidget.
label = QLabel(w) btn = QPushButton(w) |
Мы добавили два новых виджета в это приложение: QLabel и QPushButton. QLabel используется для вывода нередактируемого текста или заполнителей внутри виджета, тогда как QPushButton используется для создания кликабельной кнопки.
Здесь важно заметить, что при создании объектов label и btn вы передаете объект окна (w) конструкторам QLabel и QPushButton. Вот как работает вложение в PyQt5. Чтобы создать виджет внутри другого виджета, вы передаете ссылку на родительский виджет в конструктор дочернего элемента.
label.move(100,130) btn.move(110,150) |
move() используется для установки позиции виджета относительно его родительского виджета. В первом случае метка будет перемещена на 100 пикселей с левой стороны и на 130 пикселей сверху окна.
Точно так же кнопка будет размещена на 110 пикселей слева и на 150 пикселей сверху окна. Этот пример является грубым способом создания макетов и обычно не используется в производстве; он включен только для учебных целей. Qt поддерживает различные макеты, которые мы детально рассмотрим в следующих разделах этого руководства.
btn.clicked.connect(dialog) |
Наконец, это пример сигналов и слотов в Qt. В приложениях на основе графического интерфейса функции выполняются на основе действий, запускаемых пользователем, таких как наведение на элемент или нажатие кнопки. Эти действия называются событиями. Напомним, что метод app.exec_() передает управление в цикл обработки событий Qt. Для этого и предназначен цикл событий: прослушивать события и выполнять в ответ действия.
Каждый раз, когда происходит событие, например, когда пользователь нажимает кнопку, соответствующий виджет Qt генерирует сигнал. Эти сигналы могут быть подключены к функциям Python (например, к функции диалога в этом примере), чтобы функция выполнялась при срабатывании сигнала. Эти функции в Qt lingo называются слотами. Основной синтаксис для запуска функции слота в ответ на сигнал от события выглядит следующим образом:
widget.signal.connect(slot) |
Это означает, что всякий раз, когда сигнал запускается виджетом , будет выполняться функция подключенного слота. Таким образом, Qt использует сигналы и слоты для связи между объектами и облегчения повторного использования и интерактивности компонентов.
Теперь, когда вы знаете, как вкладывать виджеты и реализовывать взаимодействия с помощью сигналов и слотов, вот список полезных виджетов и других классов, которые вы можете использовать в приложениях PyQt.
Компоненты и виджеты
В PyQt доступно большое количество виджетов для создания приложений с помощью графического интерфейса. Однако в PyQt5 была произведены реорганизация классов в другие модули и ревизии в лицензиях.
Поэтому очень важно иметь общее представление о структуре PyQt5. В этом разделе мы рассмотрим, как PyQt5 организован внутри, и вы узнаете о различных модулях, библиотеках и классах API, предоставляемых PyQt5.
Структура каталогов PyQt5
Это фундаментальные модули, используемые связыванием Qt в Python, в частности в PyQt5.
Qt: Он объединяет все классы / модули, упомянутые ниже, в один модуль. Это значительно увеличивает объем памяти, используемой приложением. Однако управлять инфраструктурой проще, импортируя только один модуль.
QtCore: Содержит основные неграфические классы, используемые другими модулями. Именно здесь реализуются цикл событий Qt, сигналы, возможность подключения к слотам и т. д.
QtWidgets: Содержит большинство виджетов, доступных в Pyqt5.
QtGui: Содержит компоненты графического интерфейса и расширяет модуль QtCore.
QtNetwork: Содержит классы, используемые для реализации сетевого программирования через Qt. Он поддерживает TCP-серверы, TCP-сокеты, UDP-сокеты, обработку SSL, сетевых сеансов и поиск DNS.
QtMultimedia: Предоставляет низкоуровневый мультимедийный функционал.
QtSql: реализует интеграцию базы данных для баз данных SQL. Поддерживает ODBC, MySQL, Oracle, SQLite и PostgreSQL.
Виджеты PyQt5
Вот список наиболее часто используемых виджетов PyQt5:
QLineEdit: Это поле ввода, которое позволяет пользователю вводить одну строку текста.
QRadioButton: Это поле ввода с выбираемой кнопкой, аналогичное переключателям в html.
rad = QRadioButton(«button title») rad.setChecked(True) #to select the button by default. |
QComboBox: Используется для отображения выпадающего меню со списком выбираемых элементов.
drop = QComboBox(w) drop.addItems([«item one», «item two», «item three»]) |
QCheckBox: Отображает выбираемое квадратное поле перед меткой, которая отмечена, если выбрана, аналогично переключателям.
check = QCheckBox(«button title») |
QMenuBar: Отображает горизонтальную строку меню в верхней части окна. Вы можете добавить в эту панель только объекты класса QMenu. Эти объекты QMenu могут дополнительно содержать строки, объекты QAction или другие объекты QMenu.
QToolBar: Это горизонтальная панель или панель, которую можно перемещать в пределах окна. Может содержать кнопки и другие виджеты.
QTab: Используется для разбиения содержимого окна на несколько страниц, к которым можно получить доступ через разные вкладки в верхней части виджета. Он состоит из двух разделов: панель вкладок и страница вкладок.
QScrollBar: Используется для создания полос прокрутки, которые позволяют пользователю прокручивать вверх и вниз в пределах окна. Он состоит из подвижного ползунка, дорожки ползунка и двух кнопок для прокрутки ползунка вверх или вниз.
QSplitter: Разделители используются для разделения содержимого окна, чтобы виджеты были сгруппированы правильно и не выглядели нагроможденными. QSplitter является одним из основных обработчиков макетов, доступных в PyQt5, и используется для разделения содержимого как по горизонтали, так и по вертикали.
QDock: виджет-док — это подокно с двумя свойствами: оно может быть перемещено в главное окно и его можно закрепить за пределами родительского окна в другом месте на экране.
Макеты и темы
В предыдущих примерах мы использовали только методы move() и resize() для установки позиций виджетов в графическом интерфейсе.
Тем не менее, PyQt имеет мощный механизм управления компоновкой, который можно использовать для создания расширенных пользовательских интерфейсов приложений. В этом разделе вы узнаете о двух важных классах, которые используются в Qt для создания и управления макетами: QBoxLayout и QGridLayout.
QBoxLayout
QBoxLayout используется для выравнивания дочерних виджетов макета в горизонтальной или вертикальной строке. Два основных класса, которые наследуются от QBoxLayout, это:
QHBoxLayout: используется для выравнивания дочерних виджетов по горизонтали.
QVBoxLayout: используется для выравнивания дочерних виджетов по вертикали.
Например, так будут выглядеть три кнопки, выровненные по QHBoxLayout.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
import sys from PyQt5.QtWidgets import * if __name__ == «__main__»: app = QApplication([]) w = QWidget() w.setWindowTitle(«Musketeers») btn1 = QPushButton(«Athos») btn2 = QPushButton(«Porthos») btn3 = QPushButton(«Aramis») hbox = QHBoxLayout(w) hbox.addWidget(btn1) hbox.addWidget(btn2) hbox.addWidget(btn3) w.show() sys.exit(app.exec_()) |
А вот как они будут выглядеть в QVBoxLayout.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
import sys from PyQt5.QtWidgets import * if __name__ == «__main__»: app = QApplication([]) w = QWidget() w.setWindowTitle(«Musketeers») btn1 = QPushButton(«Athos») btn2 = QPushButton(«Porthos») btn3 = QPushButton(«Aramis») vb = QVBoxLayout(w) vb.addWidget(btn1) vb.addWidget(btn2) vb.addWidget(btn3) w.show() sys.exit(app.exec_()) |
Единственная функция, которая нуждается в каком-либо объяснении на данный момент, это метод addWidget(). Он используется для вставки виджетов в макет HBox или VBox. Он также используется в других макетах, где принимает другое количество параметров, как вы увидите в следующем разделе. Виджеты отображаются внутри макета в том порядке, в котором вы их вставляете.
QGridLayout
QGridLayout используется для создания интерфейсов, в которых виджеты расположены в виде сетки (например, матрицы или 2D-массива). Чтобы вставить элементы в сетку, вы можете использовать матричное представление, чтобы определить количество строк и столбцов в сетке, а также положение этих элементов.
Например, чтобы создать сетку 3 * 3 (т.е. сетку с тремя строками и тремя столбцами), вы пишите следующий код:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
import sys from PyQt5.QtWidgets import * if __name__ == «__main__»: app = QApplication([]) w = QWidget() grid = QGridLayout(w) for i in range(3): for j in range(3): grid.addWidget(QPushButton(«Button»),i,j) w.show() sys.exit(app.exec_()) |
Вывод будет следующий:
Метод addWidget() в макете сетки принимает следующие аргументы:
Объект виджета, который вы хотите добавить в сетку
X-координата объекта
Y-координата объекта
Диапазон строк (по умолчанию = 0)
Col-span (по умолчанию = 0)
Чтобы лучше это понять, вы можете вручную вставить каждый виджет, как показано ниже:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
import sys from PyQt5.QtWidgets import * if __name__ == «__main__»: app = QApplication([]) w = QWidget() grid = QGridLayout(w) grid.addWidget(QPushButton(«Button one»),0,0) grid.addWidget(QPushButton(«Button two»),0,1) grid.addWidget(QPushButton(«Button three»),1,0) grid.addWidget(QPushButton(«Button four»),1,1) w.show() sys.exit(app.exec_()) |
Вот как будет выглядеть сетка:
Вы также можете передать параметры rowspan и colspan в addWidget(), чтобы охватить более одной строки или столбца.
grid.addWidget(QPushButton(«Button five»),2,0,1,0) |
Это создаст кнопку, которая растягивается на оба столбца.
Темы
PyQt5 поставляется с некоторыми встроенными темами, которые вы можете использовать в приложениях. Метод setStyle(), вызываемый в экземпляре QApplication, используется для установки определенной темы для вашего приложения. Например, добавление следующей строки кода изменит тему приложения по умолчанию на Fusion:
Так будет выглядеть предыдущий пример в теме Fusion.
Еще одна полезная функция для создания тем приложений — это метод setPalette(). Вот код для изменения цвета различных виджетов с помощью setPalette().
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
import sys from PyQt5.QtCore import Qt from PyQt5.QtWidgets import * from PyQt5.QtGui import QPalette if __name__ == «__main__»: app = QApplication([]) app.setStyle(«Fusion») qp = QPalette() qp.setColor(QPalette.ButtonText, Qt.black) qp.setColor(QPalette.Window, Qt.black) qp.setColor(QPalette.Button, Qt.gray) app.setPalette(qp) w = QWidget() grid = QGridLayout(w) grid.addWidget(QPushButton(«Button one»),0,0) grid.addWidget(QPushButton(«Button two»),0,1) grid.addWidget(QPushButton(«Button three»),1,0) grid.addWidget(QPushButton(«Button four»),1,1) w.show() sys.exit(app.exec_()) |
Вот результат:
Чтобы использовать метод setPalette(), сначала нужно определить палитру. Это делается путем создания объекта класса QPalette.
Обратите внимание, что класс QPalette принадлежит модулю QtGui, и вам нужно будет импортировать его, чтобы это работало. Создав объект QPalette, используйте метод setColor(), чтобы передать имя виджета, цвет которого вы хотите изменить, и цвет, который вы хотите установить.
qp.setColor(QPalette.Window, Qt.black) |
Это изменит цвет окна на черный. После того, как вы определили цветовую схему, используйте функцию setPalette(), чтобы применить палитру к приложению.
Это все, что вам нужно сделать, если вы хотите создать базовые темы для своего приложения. PyQt также позволяет использовать таблицы стилей для определения внешнего вида виджетов. Если вы знакомы с CSS, вы можете легко определить расширенные стили для приложения, используя таблицы стилей Qt.
Заключение
PyQt — это привязка Python для инфраструктуры пользовательского интерфейса C ++, Qt.
PyQt4 и PyQt5 — две основные версии, разработанные Riverbank Computing.
Основными модулями платформы PyQt являются: Qt, QtCore, QtWidgets, QtGui, QtSql, QtNetwork
PyQt поддерживает различные виджеты, такие как: Кнопки, Текстовые метки, Текстовые поля, Переключатели и чек-боксы, Панели инструментов и строки меню, Webkit, Вкладки, Доки
В PyQt интерактивность реализована с использованием сигналов и слотов.
Событие это действие, которое выполняется пользователем в графическом интерфейсе (например, нажатие кнопки).
Сигнал передается в соответствующий виджет, когда в нем происходит событие.
Слот является функцией, которая подключается к сигналу и выполняет при повышении сигнала.
PyQt имеет надежный механизм компоновки и поддерживает расширенный дизайн макета и управление им. Это две часто используемые схемы компоновки в PyQt: Макет блока, Макет сетки
PyQt позволяет создавать собственные темы для приложения с графическим интерфейсом и имеет встроенную поддержку таблиц стилей.
PyQt может использоваться для создания пользовательских интерфейсов, а также автономных приложений.
Источник: //www.guru99.com
Редакция: Команда webformyself.
Содержание
- Введение в тему
- Что такое pyqt5
- Установка pyqt
- Создание gui графического интерфейса пользователя
- Виджеты
- Макеты
- Пользовательские стили
- Встроенные стили
- Пользовательские цвета
- Таблицы стилей
- Сигналы и слоты
- Компилируем наше приложение
- Бонус создаем установщик
Введение в тему
В данном уроке по PyQt5 мы изучим, как использовать Пайтон и Qt для создания графического интерфейса пользователя в самых распространённых операционных системах.
Что такое pyqt5
PyQt – это модуль, предназначенный для создания графических интерфейсов в Python через библиотеку Qt. Эта библиотека написана на языке C++ и является одним из самых популярных инструментов разработки GUI, а также имеет обширное сообщество. Существует и альтернатива: модуль PySide. Различаются они тем, что PyQt нельзя свободно использовать в коммерческих проектах, однако, этот модуль, всё же, более зрелый. Существуют и другие распространённые средства создания графических интерфейсов:
- Kyvi
- WxPython
- Tkinter
- PyGTK
Установка pyqt
Устанавливать модуль будем в виртуальную среду. Для этого вводим в консоли:
Эта команда создаст папку venv/. Чтобы запустить виртуальную среду в ОС Windows, выполните следующую команду:
call venv/scripts/activate.bat
Для остальных ОС это делается так:
Если всё получилось, в начале строки в терминале появится префикс (venv).
Теперь, для установки PyQt с помощью pip, выполните следующую команду:
Создание gui графического интерфейса пользователя
Теперь можно приступить к созданию интерфейса. Сперва модуль надо импортировать:
from PyQt5.QtWidgets import QApplication, QLabel
Теперь необходимо создать объект приложения QApplication при помощи следующей команды:
В объект приложения необходимо передавать список аргументов. В данном случае он пустой [], но, общепринятая практика писать следующим образом:
import sys
app = QApplication(sys.argv)
sys.argv – аргументы командной строки и теперь Вы можете запустить свой скрипт из консоли, передав при этом какие-то аргументы.
Дальше нужно создать виджет (о них мы поговорим чуть позже):
label = QLabel('Hello World!')
На данный момент наш маленький интерфейс готов, но, чтобы его увидел пользователь, надо использовать метод show:
Готово:
Внешний вид будет зависеть от Вашей операционной среды.
Осталось запустить приложение:
После этой команды скрипт попадает в цикл обработки событий. Благодаря этому, мы можем понимать, что делает пользователь: заполняет поля, нажимает кнопки и так далее. Хороший вариант обрабатывать закрытие окна:
Метод sys.exit() обеспечивает чистый выход. Вы сможете узнать, как завершилось приложение.
Виджеты
Виджеты – это все видимые части интерфейса. Они могут быть вложены друг в друга.
На этом изображении представлены самые часто встречающиеся виджеты:
Они перечислены ниже в порядке сверху вниз и слева направо:
- QLabel — обеспечивает отображение текста или изображения
- QComboBox — представляет собой комбинированную кнопку и всплывающий список
- QCheckBox — предоставляет флажок с текстовой меткой
- QRadioButton — предоставляет переключатель с текстовой меткой
- QPushButton — предоставляет командную кнопку
- QTableWidget — предоставляют стандартные средства отображения таблиц для приложений
- QLineEdit – изменяемая строка
- QSlider — вертикальный или горизонтальный ползунок
- QProgressBar — предоставляет горизонтальную или вертикальную полосу выполнения
Есть ещё несколько важных методов виджетов, о которых нельзя не рассказать:
resize() — изменяет размеры виджета.
move() — двигает виджет на экране.
setWindowTitle() – устанавливает название окна.
Пример использования:
import sys
from PyQt5.QtWidgets import *
app = QApplication(sys.argv)
mywidget = QWidget()
mywidget.resize(750, 650)
mywidget.move(0, 0)
mywidget.setWindowTitle('My Window')
mywidget.show()
sys.exit(app.exec_())
Этот код создаёт пустое окно размером 750*650 пикселей, расположенное в верхнем левом углу. Название окна — ‘My Window’.
Есть ещё очень важный инструмент для создания интерфейсов — Qt Designer. Это программа, которая делает проще процесс создания графического интерфейса программы, конечно внешний вид можно сделать и без помощи данной программы, но не для всех это будет удобно. На данный момент разработчики прекратили поддержку этого инструмента.
Макеты
Чаще всего приложение состоит из целого набора виджетов. Если так, то нужно объяснить Qt, как их разместить внутри окна. Например, вы можете использовать QHBoxLayout для горизонтального расположения виджетов:
Листинг кода, создающего окно, представленное на изображении выше:
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QHBoxLayout
app = QApplication(sys.argv)
mywindow = QWidget()
mylayout = QHBoxLayout()
mylayout.addWidget(QPushButton('Hello'))
mylayout.addWidget(QPushButton('World'))
mywindow.setLayout(mylayout)
mywindow.show()
sys.exit(app.exec_())
Что здесь происходит? Сперва мы импортируем необходимые модули, затем создаём объект приложения. Создаём виджет типа QWidget. Это базовый тип, не имеющий поведения. Дальше инициируем макет (mylayout), а в нём две кнопки QPushButton. Строка mywindow.setLayout(mylayout) говорит QT что для виджета mywindow будет использоваться именно этот макет. Делаем всё это видимым и запускаем.
Qt включает набор классов управления компоновкой, которые используются для описания компоновки виджетов в пользовательском интерфейсе приложения. Эти макеты автоматически позиционируют и изменяют размер виджетов, когда объем доступного для них места изменяется, гарантируя, что они единообразно расположены и пользовательский интерфейс в целом остается пригодным для использования. Вот список макетов:
QHBoxLayout – располагает виджеты горизонтально.
QVBoxLayout — располагает виджеты вертикально.
QGridLayout – сеточный макет. Этот макет делит пространство на строки и столбцы.
QFormLayout — размещает свои дочерние элементы в виде двух столбцов.
Если Вы знакомы с языком CSS, то, конечно же, заметили что QHBoxLayout и QVBoxLayout похожи на flexbox, а QGridLayout – на grid.
Пример с QFormLayout:
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QFormLayout, QLineEdit
app = QApplication(sys.argv)
mywindow = QWidget()
mylayout = QFormLayout()
mylayout.addRow(QPushButton('Hello'), QLineEdit('World'))
mywindow.setLayout(mylayout)
mywindow.show()
sys.exit(app.exec_())
Пользовательские стили
Библиотека Qt является очень мощной, ведь с ней можно управлять почти всеми аспектами интерфейса. Не исключение и стиль оформления.
Встроенные стили
Проще всего установить для приложения глобальный стиль. Сделаем это для программы из предыдущего примера:
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QHBoxLayout, QSlider
app = QApplication(sys.argv)
mywindow = QWidget()
mylayout = QHBoxLayout()
mylayout.addWidget(QPushButton('Hello'))
mylayout.addWidget(QPushButton('World'))
mylayout.addWidget(QSlider())
mywindow.setLayout(mylayout)
mywindow.show()
app.setStyle('Fusion')
sys.exit(app.exec_())
Меняем строку: app.setStyle(‘Fusion’) на app.setStyle(‘Windows’) и стиль меняется:
Для применения стиля, необходимо использовать метод app.setStyle().
Какие стили Вы можете использовать, зависит от Вашей операционной системы. Чаще всего это: «Fusion», «Windows», «WindowsVista» (для Windows) и «Macintosh» (только для Mac).
Пользовательские цвета
Вы так же можете самостоятельно задать цвет элементов:
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPalette
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QHBoxLayout, QSlider
app = QApplication(sys.argv)
mywindow = QWidget()
mylayout = QHBoxLayout()
mylayout.addWidget(QPushButton('Hello'))
mylayout.addWidget(QPushButton('World'))
mylayout.addWidget(QSlider())
mywindow.setLayout(mylayout)
mywindow.show()
app.setStyle('Windows')
palette = QPalette()
palette.setColor(QPalette.ButtonText, Qt.black)
palette.setColor(QPalette.Button, Qt.darkGray)
palette.setColor(QPalette.Window, Qt.lightGray)
app.setPalette(palette)
sys.exit(app.exec_())
Теперь наш интерфейс оформлен в тёмных цветах.
Таблицы стилей
Так же можно использовать таблицы стилей, как в CSS. Так, мы можем изменить оформление кнопок, поменять их рамку:
import sys
from PyQt5.QtGui import QPalette
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QHBoxLayout, QSlider
app = QApplication(sys.argv)
mywindow = QWidget()
mylayout = QHBoxLayout()
mylayout.addWidget(QPushButton('Hello'))
mylayout.addWidget(QPushButton('World'))
mylayout.addWidget(QSlider())
mywindow.setLayout(mylayout)
mywindow.show()
app.setStyle('Windows')
palette = QPalette()
app.setStyleSheet("QPushButton {border: 2px dotted grey;}")
sys.exit(app.exec_())
Здесь мы использовали метод setStyleSheet и передали в него свойство CSS. Будьте осторожны, не всегда этот способ работает так, как Вы этого ожидаете.
Сигналы и слоты
В Qt есть такой механизм как сигналы. Они созданы, чтобы оповещать основной код о происходящих с интерфейсом событиях. Ниже представлен код, который создаёт окно с кнопкой. Если на эту кнопку нажать (нажатие – это событие), всплывёт оповещение.
import sys
from PyQt5.QtWidgets import *
app = QApplication(sys.argv)
mywidget = QPushButton('Hello')
def on_button_clicked():
alert = QMessageBox()
alert.setText('World')
alert.exec_()
mywidget.clicked.connect(on_button_clicked)
mywidget.show()
sys.exit(app.exec_())
Объект mywidget.clicked — это сигнал, а метод этого объекта .connect() позволяет установить на нем слот. Слот- это просто функция, которая вызывается при поступлении сигнала. Это ещё можно назвать коллбеком или функцией обратного вызова.
Компилируем наше приложение
Одна из проблем, связанных с PyQt, это распространение программ, использующих этот модуль.
В Питоне процесс создания автономного исполняемого файла из исходного кода называют замораживанием. Несмотря на то, что существует несколько модулей для таких задач, например PyInstaller, py2exe, pyqtdeploy, cx_Freeze, bbfreze, py2app и прочие, замораживание программ PyQt – задача не из простых.
Воспользуемся модулем fbs, который позволяет создавать автономные исполняемые файлы для программ PyQt. Для ее установки введите команду:
Затем выполним следующую команду:
Появится приглашение для ввода различных аргументов, таких, например, как название проекта.
Команда создает новую папку с именем src/в вашем текущем каталоге. Эта папка содержит минимальную конфигурацию для простого приложения PyQt.
Когда Вы введете команду run, должно открыться пустое окно:
Это программа PyQt5. Исходный код этого приложения находится в директории src/main/python/main.py в текущем каталоге.
Эта команда создает и помещает автономный двоичный файл в папку /MyApp/ вашего текущего каталога. Запустить его можно на любом компьютере с той же операционной системой, что и у Вас
Бонус создаем установщик
Библиотека fbs также предоставляет Вам возможность создать установщик с помощью команды fbs installer:
Иван Душенко
Автор статьи
Задать вопрос
PyQt5 tutorial
Learn how you can create a Python GUI
in 2023.
This PyQt5 tutorial shows how to use Python 3 and Qt to
create a GUI on Windows, Mac or Linux. It even covers
creating an installer for your app.
What is PyQt5?
PyQt
is a library that lets you use the
Qt GUI framework from
Python. Qt itself is written in C++. By using it from
Python, you can build applications much more quickly while
not sacrificing much of the speed of C++.
PyQt5 refers to the most recent version 5 of Qt. You may
still find the occasional mention of (Py)Qt4 on the web, but
it is old and no longer supported.
An interesting new competitor to PyQt is
Qt for Python.
Its API is virtually identical. Unlike PyQt, it is licensed
under the LGPL and can thus be used for free in commercial
projects. It’s backed by the Qt company, and thus likely the
future. We use PyQt here because it is more mature. Since
the APIs are so similar, you can easily switch your apps to
Qt for Python later.
Install PyQt
The best way to manage dependencies in Python is via a
virtual environment.
A virtual environment is simply a local directory that
contains the libraries for a specific project. This is
unlike a system-wide installation of those libraries, which
would affect all of your other projects as well.
To create a virtual environment in the current directory,
execute the following command:
python3 -m venv venv
This creates the venv/
folder. To activate the
virtual environment on Windows, run:
call venv/scripts/activate.bat
On Mac and Linux, use:
source venv/bin/activate
You can see that the virtual environment is active by the
(venv)
prefix in your shell:
To now install PyQt, issue the following command:
pip install PyQt5
Congratulations! You’ve successfully set up PyQt5.
Create a GUI
Time to write our very first GUI app! With the virtual
environment still active, start Python. We will execute the
following commands:
First, we tell Python to load PyQt via the import statement:
from PyQt5.QtWidgets import QApplication, QLabel
Next, we create a
QApplication
with the command:
app = QApplication([])
This is a requirement of Qt: Every GUI app must have exactly
one instance of QApplication
. Many parts of Qt
don’t work until you have executed the above line. You will
therefore need it in virtually every (Py)Qt app you write.
The brackets []
in the above line represent the
command line arguments passed to the application. Because
our app doesn’t use any parameters, we leave the brackets
empty.
Now, to actually see something, we create a simple label:
label = QLabel('Hello World!')
Then, we tell Qt to show the label on the screen:
label.show()
Depending on your operating system, this already opens a
tiny little window:
The last step is to hand control over to Qt and ask it to
«run the application until the user closes it». This is done
via the command:
app.exec()
If all this worked as expected then well done! You’ve just
built your first GUI app with Python and Qt.
Widgets
Everything you see in a (Py)Qt app is a
widget:
Buttons, labels, windows, dialogs, progress bars etc.
Like HTML elements, widgets are often nested. For example, a
window can contain a button, which in turn contains a label.
The following screenshot shows the most common Qt widgets:
Top-to-bottom, left-to-right, they are:
- QLabel
- QComboBox
- QCheckBox
- QRadioButton
- QPushButton
- QTableWidget
- QLineEdit
- QSlider
- QProgressBar
You can download the code for the app shown in the
screenshot
here, if you are interested.
Layouts
Like the example above, your GUI will most likely consist of
multiple widgets. In this case, you need to tell Qt how to
position them. For instance, you can use
QVBoxLayout
to stack widgets vertically:
The code for this screenshot is:
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QVBoxLayout app = QApplication([]) window = QWidget() layout = QVBoxLayout() layout.addWidget(QPushButton('Top')) layout.addWidget(QPushButton('Bottom')) window.setLayout(layout) window.show() app.exec()
As before, we instantiate a QApplication
. Then,
we create a window
. We use the most basic type
QWidget
for it because it merely acts as a
container and we don’t want it to have any special behavior.
Next, we create the layout
and add two
QPushButton
s to it. Finally, we tell the window
to use this layout (and thus its contents). As in our first
application, we end with calls to .show()
and
app.exec()
.
There are of course many other kinds of layouts (eg.
QHBoxLayout to lay out items in a row). See
Qt’s documentation
for an overview.
Custom styles
One of Qt’s strengths is its support for custom styles.
There are many mechanisms that let you customize the look
and feel of your application. This section outlines a few.
Built-in styles
The coarsest way to change the appearance of your
application is to set the global
Style. Recall the widgets screenshot above:
This uses a style called Fusion
. If you use
the Windows
style instead, then it looks as
follows:
To apply a style, use app.setStyle(...)
:
from PyQt5.QtWidgets import * app = QApplication([]) app.setStyle('Fusion') ...
The available styles depend on your platform but are usually
'Fusion'
, 'Windows'
,
'WindowsVista'
(Windows only) and
'Macintosh'
(Mac only).
Custom colors
If you like a style, but want to change its colors (eg. to a
dark theme), then you can use
QPalette
and app.setPalette(...)
. For example:
from PyQt5.QtCore import Qt from PyQt5.QtGui import QPalette from PyQt5.QtWidgets import QApplication, QPushButton app = QApplication([]) app.setStyle('Fusion') palette = QPalette() palette.setColor(QPalette.ButtonText, Qt.red) app.setPalette(palette) button = QPushButton('Hello World') button.show() app.exec()
This changes the text color in buttons to red:
For a dark theme of the Fusion style, see
here.
Style sheets
In addition to the above, you can change the appearance of
your application via style sheets. This is Qt’s
analogue of CSS. We can use this for example to add some
spacing:
from PyQt5.QtWidgets import QApplication, QPushButton app = QApplication([]) app.setStyleSheet("QPushButton { margin: 10ex; }") button = QPushButton('Hello World') button.show() app.exec()
For more information about style sheets, please see
Qt’s documentation.
Signals / slots
Qt uses a mechanism called signals to let you react
to events such as the user clicking a button. The following
example illustrates this. It contains a button that, when
clicked, shows a message box:
from PyQt5.QtWidgets import * app = QApplication([]) button = QPushButton('Click') def on_button_clicked(): alert = QMessageBox() alert.setText('You clicked the button!') alert.exec() button.clicked.connect(on_button_clicked) button.show() app.exec()
The interesting line is highlighted above:
button.clicked
is a signal,
.connect(...)
lets us install a so-called
slot on it. This is simply a function that gets
called when the signal occurs. In the above example, our
slot shows a message box.
The term slot is important when using Qt from C++, because
slots must be declared in a special way in C++. In Python
however, any function can be a slot – we saw this
above. For this reason, the distinction between slots and
«normal» functions has little relevance for us.
Signals are ubiquitous in Qt. And of course, you can also
define your own. This however is beyond the scope of this
tutorial.
Compile your app
You now have the basic knowledge for creating a GUI that
responds to user input. Say you’ve written an app. It runs
on your computer. How do you give it to other people, so
they can run it as well?
You could ask the users of your app to install Python and
PyQt like we did above, then give them your source code. But
that is very tedious (and usually impractical). What we want
instead is a standalone version of your app. That
is, a binary executable that other people can run on their
systems without having to install anything.
In the Python world, the process of turning source code into
a self-contained executable is called freezing.
Although there are many libraries that address this issue
– such as PyInstaller, py2exe, cx_Freeze, bbfreze,
py2app, … – freezing PyQt apps has traditionally
been a surprisingly hard problem.
We will use a new library called
fbs that lets you
create standalone executables for PyQt apps. To install it,
enter the command:
pip install fbs
Then, execute the following:
fbs startproject
This prompts you for a few values:
When you type in the suggested run
command,
an empty window should open:
This is a PyQt5 app just like the ones we have seen before.
Its source code is in src/main/python/main.py
in your current directory. But here’s the cool part: We can
use fbs to turn it into a standalone executable!
fbs freeze
This places a self-contained binary in the
target/MyApp/
folder of your current directory.
You can send it to your friends (with the same OS as yours)
and they will be able to run your app!
(Please note that the free version of fbs only supports
Python 3.5 or 3.6. If you have a different version, please
install one of these supported Python versions or buy
fbs Pro).
Bonus: Create an installer
fbs also lets you create an installer for your app via the
command fbs installer
:
(If you are on Windows, you first need to install
NSIS and
place it on your PATH
.)
For more information on how you can use fbs for your
existing application, please see
this article.
Or
fbs’s tutorial.
Summary
If you have made it this far, then big congratulations.
Hopefully, you now have a good idea of how PyQt (and its
various parts) can be used to write a desktop application
with Python. We also saw how fbs lets you create standalone
executables and installers.
Due to the popularity of this article, I wrote a
PyQt6 book.
The book explains in more detail how you can create your own
apps. Even Phil Thompson, the creator of PyQt, read the book
and said it’s «very good». So
check it out!
Michael has been working with PyQt5 since 2016, when
he started
fman,
a cross-platform file manager. Frustrated with the
difficulties of creating a desktop app, Michael open
sourced
fman’s build system (fbs). It saves you
months when creating Python Qt GUIs. Recently,
Michael also wrote a popular
book
about these two technologies.