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 Технический Университет Молдовы, Магистр, Магистерская диссертация «Идентификация человека в киберпространстве по фотографии лица»
От автора: что такое 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.
Эта статья предназначена для тех, кто только начинает своё знакомство с созданием приложений с графическим интерфейсом (GUI) на Python. В ней мы рассмотрим основы использования PyQt в связке с Qt Designer. Шаг за шагом мы создадим простое Python GUI приложение, которое будет отображать содержимое выбранной директории.
Что нам потребуется
Нам понадобятся PyQt и Qt Designer, ну и Python, само собой.
В этой статье используется PyQt5 с Python 3, но особых различий между PyQt и PySide или их версиями для Python 2 нет.
Windows: PyQt можно скачать здесь. В комплекте с ним идёт Qt Designer.
macOS: Вы можете установить PyQt с помощью Homebrew:
$ brew install pyqt5
Скачать пакет с большинством компонентов и инструментов Qt, который содержит Qt Designer, можно по этой ссылке.
Linux: Всё нужное, вероятно, есть в репозиториях вашего дистрибутива. Qt Designer можно установить из Центра Приложений, но PyQt придётся устанавливать через терминал. Установить всё, что нам понадобится, одной командой можно, например, так:
# для Fedora:
$ sudo dnf install python3-qt5 qt-creator
# для Debian/Ubuntu:
$ sudo apt install python3-qt5 pyqt5-dev-tools qtcreator
После того как вы закончили с приготовлениями, откройте командную строку/терминал и убедитесь, что вы можете использовать команду pyuic5
. Вы должны увидеть следующее:
$ pyuic5
Error: one input ui-file must be specified
Если вы видите сообщение, что такой команды нет или что-то в таком роде, попробуйте загуглить решение проблемы для вашей операционной системы и версии PyQt.
Если вы используете Windows, то, скорее всего, путь C:Python36Scripts
(измените 36
на вашу версию Python) не прописан в вашем PATH
. Загляните в этот тред на Stack Overflow, чтобы узнать, как решить проблему.
Дизайн
Основы
Теперь, когда у нас всё готово к работе, давайте начнём с простого дизайна.
Откройте Qt Designer, где вы увидите диалог новой формы, выберите Main Window и нажмите Create.
После этого у вас должна появиться форма — шаблон для окна, размер которого можно менять и куда можно вставлять объекты из окна виджетов и т.д. Ознакомьтесь с интерфейсом, он довольно простой.
Теперь давайте немного изменим размер нашего главного окна, т.к. нам не нужно, чтобы оно было таким большим. А ещё давайте уберём автоматически добавленное меню и строку состояния, поскольку в нашем приложении они не пригодятся.
Все элементы формы и их иерархия по умолчанию отображаются в правой части окна Qt Designer под названием Object Inspector. Вы с лёгкостью можете удалять объекты, кликая по ним правой кнопкой мыши в этом окне. Или же вы можете выбрать их в основной форме и нажать клавишу DEL на клавиатуре.
В итоге мы имеем почти пустую форму. Единственный оставшийся объект — centralwidget
, но он нам понадобится, поэтому с ним мы ничего не будем делать.
Теперь перетащите куда-нибудь в основную форму List Widget (не List View) и Push Button из Widget Box.
Макеты
Вместо использования фиксированных позиций и размеров элементов в приложении лучше использовать макеты. Фиксированные позиции и размеры у вас будут выглядеть хорошо (пока вы не измените размер окна), но вы никогда не можете быть уверены, что всё будет точно так же на других машинах и/или операционных системах.
Макеты представляют собой контейнеры для виджетов, которые будут удерживать их на определённой позиции относительно других элементов. Поэтому при изменении размера окна размер виджетов тоже будет меняться.
Давайте создадим нашу первую форму без использования макетов. Перетащите список и кнопку в форме и измените их размер, чтобы вышло вот так:
Теперь в меню Qt Designer нажмите Form, затем выберите Preview и увидите что-то похожее на скриншот выше. Выглядит хорошо, не так ли? Но вот что случится, когда мы изменим размер окна:
Наши объекты остались на тех же местах и сохранили свои размеры, несмотря на то что размер основного окна изменился и кнопку почти не видно. Вот поэтому в большинстве случаев стоит использовать макеты. Конечно, бывают случаи, когда вам, например, нужна фиксированная или минимальная/максимальная ширина объекта. Но вообще при разработке приложения лучше использовать макеты.
Основное окно уже поддерживает макеты, поэтому нам ничего не нужно добавлять в нашу форму. Просто кликните правой кнопкой мыши по Main Window в Object Inspector и выберите Lay out → Lay out vertically. Также вы можете кликнуть правой кнопкой по пустой области в форме и выбрать те же опции:
Ваши элементы должны быть в том же порядке, что и до внесённых изменений, но если это не так, то просто перетащите их на нужное место.
Так как мы использовали вертикальное размещение, все элементы, которые мы добавим, будут располагаться вертикально. Можно комбинировать размещения для получения желаемого результата. Например, горизонтальное размещение двух кнопок в вертикальном будет выглядеть так:
Если у вас не получается переместить элемент в главном окне, вы можете сделать это в окне Object Inspector.
Последние штрихи
Теперь, благодаря вертикальному размещению, наши элементы выровнены правильно. Единственное, что осталось сделать (но не обязательно), — изменить имя элементов и их текст.
В простом приложении вроде этого с одним лишь списком и кнопкой изменение имён не обязательно, так как им в любом случае просто пользоваться. Тем не менее правильное именование элементов — то, к чему стоит привыкать с самого начала.
Свойства элементов можно изменить в разделе Property Editor.
Подсказка: вы можете менять размер, передвигать или добавлять часто используемые элементы в интерфейс Qt Designer для ускорения рабочего процесса. Вы можете добавлять скрытые/закрытые части интерфейса через пункт меню View.
Нажмите на кнопку, которую вы добавили в форму. Теперь в Property Editor вы должны видеть все свойства этого элемента. В данный момент нас интересуют objectName
и text
в разделе QAbstractButton
. Вы можете сворачивать разделы в Property Editor нажатием по названию раздела.
Измените значение objectName
на btnBrowse
и text
на Выберите папку.
Должно получиться так:
Именем объекта списка является listWidget
, что вполне подходит в данном случае.
Сохраните дизайн как design.ui
в папке проекта.
Превращаем дизайн в код
Конечно, можно использовать .ui
-файлы напрямую из Python-кода, однако есть и другой путь, который может показаться легче. Можно конвертировать код .ui
-файла в Python-файл, который мы потом сможем импортировать и использовать. Для этого мы используем команду pyuic5
из терминала/командной строки.
Чтобы конвертировать .ui
-файл в Python-файл с названием design.py
, используйте следующую команду:
$ pyuic5 path/to/design.ui -o output/path/to/design.py
Пишем код
Теперь у нас есть файл design.py
с нужной частью дизайна нашего приложения и мы начинать работу над созданием его логики.
Создайте файл main.py
в папке, где находится design.py
.
Другие интересные статьи по Python.
Используем дизайн
Для Python GUI приложения понадобятся следующие модули:
import sys # sys нужен для передачи argv в QApplication
from PyQt5 import QtWidgets
Также нам нужен код дизайна, который мы создали ранее, поэтому его мы тоже импортируем:
import design # Это наш конвертированный файл дизайна
Так как файл с дизайном будет полностью перезаписываться каждый раз при изменении дизайна, мы не будем изменять его. Вместо этого мы создадим новый класс ExampleApp
, который объединим с кодом дизайна для использования всех его функций:
class ExampleApp(QtWidgets.QMainWindow, design.Ui_MainWindow):
def __init__(self):
# Это здесь нужно для доступа к переменным, методам
# и т.д. в файле design.py
super().__init__()
self.setupUi(self) # Это нужно для инициализации нашего дизайна
В этом классе мы будем взаимодействовать с элементами интерфейса, добавлять соединения и всё остальное, что нам потребуется. Но для начала нам нужно инициализировать класс при запуске кода. С этим мы разберёмся в функции main()
:
def main():
app = QtWidgets.QApplication(sys.argv) # Новый экземпляр QApplication
window = ExampleApp() # Создаём объект класса ExampleApp
window.show() # Показываем окно
app.exec_() # и запускаем приложение
И чтобы выполнить эту функцию, мы воспользуемся привычной конструкцией:
if __name__ == '__main__': # Если мы запускаем файл напрямую, а не импортируем
main() # то запускаем функцию main()
В итоге main.py
выглядит таким образом:
import sys # sys нужен для передачи argv в QApplication
from PyQt5 import QtWidgets
import design # Это наш конвертированный файл дизайна
class ExampleApp(QtWidgets.QMainWindow, design.Ui_MainWindow):
def __init__(self):
# Это здесь нужно для доступа к переменным, методам
# и т.д. в файле design.py
super().__init__()
self.setupUi(self) # Это нужно для инициализации нашего дизайна
def main():
app = QtWidgets.QApplication(sys.argv) # Новый экземпляр QApplication
window = ExampleApp() # Создаём объект класса ExampleApp
window.show() # Показываем окно
app.exec_() # и запускаем приложение
if __name__ == '__main__': # Если мы запускаем файл напрямую, а не импортируем
main() # то запускаем функцию main()
Если запустить этот код: $ python3 main.py
, то наше приложение запустится!
Но нажатие на кнопку ничего не даёт, поэтому нам придётся с этим разобраться.
Добавляем функциональность в наше Python GUI приложение
Примечание Весь дальнейший код пишется внутри класса ExampleApp
.
Начнём с кнопки Выберите папку. Привязать к функции событие вроде нажатия на кнопку можно следующим образом:
self.btnBrowse.clicked.connect(self.browse_folder)
Добавьте эту строку в метод __init__
класса ExampleApp
, чтобы выполнить привязку при запуске приложения. А теперь взглянем на неё поближе:
self.btnBrowse
: здесьbtnBrowse
— имя объекта, который мы определили в Qt Designer.self
говорит само за себя и означает принадлежность к текущему классу;clicked
— событие, которое мы хотим привязать. У разных элементов разные события, например, у виджетов списка естьitemSelectionChanged
и т.д.;connect()
— метод, который привязывает событие к вызову переданной функции;self.browse_folder
— просто функция (метод), которую мы описали в классеExampleApp
.
Для открытия диалога выбора папки мы можем использовать встроенный метод QtWidgets.QFileDialog.getExistingDirectory
:
directory = QtWidgets.QFileDialog.getExistingDirectory(self, "Выберите папку")
Если пользователь выберет директорию, переменной directory
присвоится абсолютный путь к выбранной директории, в противном случае она будет равна None
. Чтобы не выполнять код дальше, если пользователь закроет диалог, мы используем команду if directory:
.
Для отображения содержимого директории нам нужно импортировать os
:
import os
И получить список содержимого следующим образом:
os.listdir(path)
Для добавления элементов в listWidget
мы используем метод addItem()
, а для удаления всех элементов у нас есть self.listWidget.clear()
.
В итоге функция browse_folder
должна выглядеть так:
def browse_folder(self):
self.listWidget.clear() # На случай, если в списке уже есть элементы
directory = QtWidgets.QFileDialog.getExistingDirectory(self, "Выберите папку")
# открыть диалог выбора директории и установить значение переменной
# равной пути к выбранной директории
if directory: # не продолжать выполнение, если пользователь не выбрал директорию
for file_name in os.listdir(directory): # для каждого файла в директории
self.listWidget.addItem(file_name) # добавить файл в listWidget
Теперь, если запустить приложение, нажать на кнопку и выбрать директорию, мы увидим:
Так выглядит весь код нашего Python GUI приложения:
import sys # sys нужен для передачи argv в QApplication
import os # Отсюда нам понадобятся методы для отображения содержимого директорий
from PyQt5 import QtWidgets
import design # Это наш конвертированный файл дизайна
class ExampleApp(QtWidgets.QMainWindow, design.Ui_MainWindow):
def __init__(self):
# Это здесь нужно для доступа к переменным, методам
# и т.д. в файле design.py
super().__init__()
self.setupUi(self) # Это нужно для инициализации нашего дизайна
self.btnBrowse.clicked.connect(self.browse_folder) # Выполнить функцию browse_folder
# при нажатии кнопки
def browse_folder(self):
self.listWidget.clear() # На случай, если в списке уже есть элементы
directory = QtWidgets.QFileDialog.getExistingDirectory(self, "Выберите папку")
# открыть диалог выбора директории и установить значение переменной
# равной пути к выбранной директории
if directory: # не продолжать выполнение, если пользователь не выбрал директорию
for file_name in os.listdir(directory): # для каждого файла в директории
self.listWidget.addItem(file_name) # добавить файл в listWidget
def main():
app = QtWidgets.QApplication(sys.argv) # Новый экземпляр QApplication
window = ExampleApp() # Создаём объект класса ExampleApp
window.show() # Показываем окно
app.exec_() # и запускаем приложение
if __name__ == '__main__': # Если мы запускаем файл напрямую, а не импортируем
main() # то запускаем функцию main()
Это были основы использования Qt Designer и PyQt для разработки Python GUI приложения. Теперь вы можете спокойно изменять дизайн приложения и использовать команду pyuic5
без страха потерять написанный код.
Перевод статьи «PyQt: Getting started with PyQt and Qt Designer»
Summary: in this tutorial, you’ll learn how to use the Qt Designer tool to design user interfaces for PyQt applications.
Install the PyQt tools
PyQt6 tools are compatible with Python 3.9 at the time of writing this tutorial. Therefore, you need to install Python 3.9 to continue the tutorial.
Note that if you have Python 3.10 or higher, you can install Python 3.9 in a separate directory and use PyQt6 tools. For example, you can install Python 3.9 in the C:Python39 directory on Windows.
Create a new virtual environment
First, create a directory to host the PyQt6 projects e.g., D:pyqt6
mkdir pyqt6
Code language: Python (python)
Second, create a virtual environment using Python 3.9 using the venv
module:
python -m venv D:pyqt6pyqt6-env
Code language: Python (python)
Activate the virtual environment
First, navigate to the pyqt6-env
virtual environment directory:
cd D:pyqt6pyqt6-env
Code language: Python (python)
Second, navigate to the Scripts
folder:
cd Scripts
Code language: Python (python)
Third, activate the virtual environment by executing the activate.bat file:
activate
Code language: Python (python)
It’ll show the following on Windows:
(pyqt6-env) d:pyqt6pyqt6-envScripts>
Code language: Python (python)
Install PyQt6 and its tools
First, execute the following command to install pyqt6
package in the pyqt6-env
virtual environment:
pip install pyqt6
Code language: Python (python)
Second, install the pyqt6-tools
package that contains the Qt Designer and other related tools:
pip install pyqt6-tools
Code language: Python (python)
The pyqt-tools
package will install the Qt Designer in the following location:
D:pyqt6pyqt6-envLibsite-packagesqt6_applicationsQtbindesigner.exe
Code language: Python (python)
Third, execute the pyuic6
command (within the pyqt6-env
virtual environment) to check the version:
pyuic6 -V
Code language: Python (python)
And you’ll see the following output:
6.1.0
Code language: Python (python)
The pyuic6 is a tool for converting a design file (.ui
) generated by Qt Designer to a Python file (.py
).
Launch the Qt Designer
From the Shell, type the designer
command to launch the Qt Designer:
(pyqt6-env) d:pyqt6pyqt6-envScripts>designer
Code language: Python (python)
The Qt Designer will look like this:
Creating a login form
We’ll create a simple login form using the Qt designer and load it into our Python program.
First, select File > New
or press Ctrl-N
keyboard shortcut to open the New Form dialog:
Second, select the Widget
from the templatesforms
and click the Create
button:
It’ll create a QWidget
as follows:
You can set the layout for the widget, and drag and drop widgets from the Widget Box to the form.
Setting widget properties
In the Property Editor, you can set a name for the widget e.g., login_form
and the window title:
Adding widgets to the login form
First, add the widgets QLabel
, QLineEdit
, and QPushButton
to the form:
The following table lists the fields, their types, and names:
Field | Widget | Object Name |
---|---|---|
Login Window | QWidget |
login_form |
Email Address | QLineEdit |
email_line_edit |
Password | QLineEdit |
password_line_edit |
Login Button | QPushButton |
btn_login |
Second, set the echo mode of the password field to Password
:
Third, right-click the widget and set its layout to Form Layout:
The form will change to the following:
Fourth, change the size of the Login
button by setting its Horizontal Size Policy to Fixed:
Fifth, save the form to the D:pyqt6
directory as login_form.ui
file.
Sixth, select Form > Preview...
menu or the keyboard shortcut Ctrl-R
to preview the form:
Finally, close the Qt Designer.
There’re two ways to use the login_form
.ui from a Python program:
- Convert the .ui file to Python code and use the generated code from the program.
- Directly use the .ui file in the program.
Converting .ui file to Python code
First, execute the following command to convert the login_form.ui
file to login_form.py
file:
pyuic6 -o login_form.py login_form.ui
Code language: Python (python)
Note that you need to run the pyuic6
from the pyqt6-env virtual environment.
The pyuic6
generated the login_form.py
from the login_form.ui
file. The login_form.py
contains the following generated Python code:
# Form implementation generated from reading ui file 'login_form.ui'
#
# Created by: PyQt6 UI code generator 6.1.0
#
# WARNING: Any manual changes made to this file will be lost when pyuic6 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt6 import QtCore, QtGui, QtWidgets
class Ui_login_form(object):
def setupUi(self, login_form):
login_form.setObjectName("login_form")
login_form.resize(269, 108)
self.formLayout = QtWidgets.QFormLayout(login_form)
self.formLayout.setObjectName("formLayout")
self.label = QtWidgets.QLabel(login_form)
self.label.setObjectName("label")
self.formLayout.setWidget(0, QtWidgets.QFormLayout.ItemRole.LabelRole, self.label)
self.email_line_edit = QtWidgets.QLineEdit(login_form)
self.email_line_edit.setObjectName("email_line_edit")
self.formLayout.setWidget(0, QtWidgets.QFormLayout.ItemRole.FieldRole, self.email_line_edit)
self.label_2 = QtWidgets.QLabel(login_form)
self.label_2.setObjectName("label_2")
self.formLayout.setWidget(1, QtWidgets.QFormLayout.ItemRole.LabelRole, self.label_2)
self.password_line_edit = QtWidgets.QLineEdit(login_form)
self.password_line_edit.setEchoMode(QtWidgets.QLineEdit.EchoMode.Password)
self.password_line_edit.setObjectName("password_line_edit")
self.formLayout.setWidget(1, QtWidgets.QFormLayout.ItemRole.FieldRole, self.password_line_edit)
self.btn_login = QtWidgets.QPushButton(login_form)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Fixed, QtWidgets.QSizePolicy.Policy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.btn_login.sizePolicy().hasHeightForWidth())
self.btn_login.setSizePolicy(sizePolicy)
self.btn_login.setObjectName("btn_login")
self.formLayout.setWidget(2, QtWidgets.QFormLayout.ItemRole.FieldRole, self.btn_login)
self.retranslateUi(login_form)
QtCore.QMetaObject.connectSlotsByName(login_form)
def retranslateUi(self, login_form):
_translate = QtCore.QCoreApplication.translate
login_form.setWindowTitle(_translate("login_form", "Login"))
self.label.setText(_translate("login_form", "Email Address"))
self.label_2.setText(_translate("login_form", "Password"))
self.btn_login.setText(_translate("login_form", "Login"))
Code language: Python (python)
It’s important to note that you should never manually change the login_form.py file. Because all your manual adjustments will be lost if you edit the login_form.ui
in the Qt Designer and regenerate the login_form.py
again.
Second, create the login.py
file and import the login_ui.py
file:
import sys
from PyQt6.QtWidgets import QApplication, QWidget
from login_form import Ui_login_form
class Login(QWidget):
def __init__(self):
super().__init__()
# use the Ui_login_form
self.ui = Ui_login_form()
self.ui.setupUi(self)
# show the login window
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
login_window = Login()
sys.exit(app.exec())
Code language: Python (python)
How it works.
- Import
Ui_login_form
class from thelogin_form.py
file - Create a new instance of the
Ui_login_form
and call thesetupUi()
method to set up the user interfaces.
Third, execute the login.py
file:
python login.py
Code language: Python (python)
It’ll show the login window:
Referencing child widgets
To use the child widgets of Ui_login_form
widget, you reference their names using the self.ui
variable.
For example, you can add a simple authentication when the user enters an email address and password and click the Login button as follows:
import sys
from PyQt6.QtWidgets import QApplication, QWidget, QMessageBox
from login_form import Ui_login_form
class Login(QWidget):
def __init__(self):
super().__init__()
# use the Ui_login_form
self.ui = Ui_login_form()
self.ui.setupUi(self)
# authenticate when the login button is clicked
self.ui.btn_login.clicked.connect(self.authenticate)
# show the login window
self.show()
def authenticate(self):
email = self.ui.email_line_edit.text()
password = self.ui.password_line_edit.text()
if email == 'john@test.com' and password == '123456':
QMessageBox.information(self, 'Success',"You're logged in!")
else:
QMessageBox.critical(self, 'Error',"Invalid email or password.")
if __name__ == '__main__':
app = QApplication(sys.argv)
login_window = Login()
sys.exit(app.exec())
Code language: Python (python)
How it works.
First, connect the clicked signal of the button to the authenticate method. Notice that we reference the btn_login
button via the self.ui
variable:
self.ui.btn_login.clicked.connect(self.authenticate)
Code language: Python (python)
Second, define the authenticate()
method that gets values from the email_line_edit
and password_line_edit
and perform a simple check of these values against hard-coded values:
def authenticate(self):
email = self.ui.email_line_edit.text()
password = self.ui.password_line_edit.text()
if email == 'john@test.com' and password == '123456':
QMessageBox.information(self, 'Success',"You're logged in!")
else:
QMessageBox.critical(self, 'Error',"Invalid email or password.")
Code language: Python (python)
Security Notice: Never do this in real applications.
Besides creating an instance of the Ui_login_form
inside the login window, you can inherit the Ui_login_form
window using multiple inheritances and directly reference the child widgets like this:
import sys
from PyQt6.QtWidgets import QApplication, QWidget, QMessageBox
from login_form import Ui_login_form
class Login(QWidget,Ui_login_form):
def __init__(self):
super().__init__()
# setup the UI
self.setupUi(self)
# authenticate when the login button is clicked
self.btn_login.clicked.connect(self.authenticate)
# show the login window
self.show()
def authenticate(self):
email = self.email_line_edit.text()
password = self.password_line_edit.text()
if email == 'john@test.com' and password == '123456':
QMessageBox.information(self, 'Success',"You're logged in!")
else:
QMessageBox.critical(self, 'Error',"Invalid email or password.")
if __name__ == '__main__':
app = QApplication(sys.argv)
login_window = Login()
sys.exit(app.exec())
Code language: Python (python)
Using .ui file directly
Another way to use the design generated by the Qt Designer is to load the .ui
file directly using the loadUi()
function of the uic
module:
from PyQt6.QtWidgets import QApplication, QWidget, QMessageBox
from PyQt6 import uic
import sys
class Login(QWidget):
def __init__(self):
super().__init__()
self.ui = uic.loadUi('login_form.ui', self)
# authenticate when the login button is clicked
self.ui.btn_login.clicked.connect(self.authenticate)
self.show()
def authenticate(self):
email = self.email_line_edit.text()
password = self.password_line_edit.text()
if email == 'john@test.com' and password == '123456':
QMessageBox.information(self, 'Success',"You're logged in!")
else:
QMessageBox.critical(self, 'Error',"Invalid email or password.")
if __name__ == '__main__':
app = QApplication(sys.argv)
login_window = Login()
sys.exit(app.exec())
Code language: Python (python)
The loadUi()
function returns an instance of the QWidget
and you can reference the child widgets via the self.ui
variable.
When you should use Qt Designer
The .ui file generated by the Qt designer creates an abstraction layer between the available widget and the code that consumes it.
Therefore, if you are starting out with PyQt, you should code the UI
manually instead of using Qt Designer. By doing this, you know exactly what widgets are available in the application.
However, if you’re familiar with PyQt and work on a large application, you should use Qt Designer to create a good design and improve productivity.
Summary
- Use Qt Designer to design user interfaces for large applications.
- Use the
pyuic6
tool to convert a .ui file into a Python source code file. - Use
loadUi()
function of theuic
module to load the.ui
file directly.
Did you find this tutorial helpful ?
Qt designer python tutorial : The Qt is pronounced as a cute and free open-source toolkit used for creating GUI applications.
The Qt Designer will help you to build a GUI (graphical user interface) and load a GUI from Python.
You need to install,
- Python
- Pyqt
- Qt designer
We need a 32-bit or 64-bit installer which depends on the architecture of your system.
The file qt-unified-linux-x86-online.run is the 32-bit installer and qt-unified-linux-x64-online.run is the 64-bit.
You can run the Linux command arch and examine the output.
The output of «i686″will indicate 32-bit and «x86_64» is 64-bit on Intel.
Then install Designer (Ubuntu Linux) with:
Sudo apt-get install qttools5-tools
Sudo apt-get install qttools5-dev
We start the designer by writing the designer in the command line.
On Ubuntu Linux:-
Cd/usr/lib/x86_64-linux-gnu/qt5/bin/
. /designer
Then we choose the “Main Window” and click on create.
We can resize the form and drag and drop widgets.
Qt designer python tutorial
Export Design to UI:-
We Click File > Save As > yourname.ui and we convert the ui code to a python file.
Pyuic5/home/Linux/helloworld.ui-0 helloworld.py
Example to load ui file,
From pyqt5 import Qtcore, QtGui, QtWidgets
From pyQt.QtWidgets import QApplication
Import sys
Import helloworld
Class exampleApp (QtWidgets.QMainWindow, helloworld.Ui_MainWindow):
Def_init_ (self, parent=none):
Super(ExampleApp, self)._init_ (parent)
Self.setupUi (self)
Defmain ():
App=QApplication (sys.argv)
Form=ExampleApp ()
Form.show ()
App.exec_ ()
If_name_==’_main_’:
Main()
Qt Designer’s Editing Modes
The objects on the form need to be placed into layouts that ensures the objects will be displayed properly when the form is used in an application.
Placing the objects in a layout also ensures that they will be resized correctly when the form is resized.
A top-level layout is used to ensure that your widgets will resize correctly when its window is resized.
Layout Objects:-
The objects are created by applying a layout to a group of existing objects.
It is achieved by selecting the objects that you need to manage and applying one of the standard layouts using the main toolbar.
The layout object can be selected and placed within the layout along with other widgets and layout objects to build a layout hierarchy.
Inserting Objects Into a Layout:-
The objects can be inserted into an existing layout by dragging them from their current positions and dropping them at the required location.
The cursor having a blue color is displayed in the layout as an object is dragged over it to indicate where the object will be added.
Types of layouts are:-
Horizontal and Vertical Layouts:-
It is the simplest way to arrange objects on a form is to place them in a horizontal or vertical layout.
The horizontal layouts ensure as widgets within are aligned horizontally, vertical layouts ensure that they are aligned vertically.
The horizontal and vertical layouts can be together combined and nested to any depth.
The Grid Layout:-
It can be created by placing objects in a grid layout.
The grid arrangement is much more suitable than a nested arrangement of horizontal and vertical layouts.
Qt Designer Manual:-
Here the Qt tool is used for designing and building GUI.
Then we compose and customize windows also test them using the styles and resolution.
The widgets and forms are created with Qt Designer and programmed code using signals.
It can be changed within the code with features as a custom plug that allows you to use the components.
The Qt designer will include four steps as,
Choosing form and objects.
Then lay objects out on the form
Then we can connect signals to slots
We preview the form.
We design a small widget that contains the controls needed to manipulate Red, Green and, Blue (RGB) values.
Select the «RED» label and hold down Ctrl then select its spin box and slider.
We repeat the step for the other two labels along with their spin boxes and sliders as well.
The next step is to combine all three layouts into one main layout and the main layout is the top-level widget’s layout.
The widgets on your window will not resize when the window is resized.
To set the layout we Right-click on your form of the three separate layouts, and select layout horizontally.
To do this, you have to switch to Edit Signals either by pressing F4 or selecting Edit Signals/Slots from the Edit menu.
We repeat the step and click on the spin box and dragging the cursor towards the slider.
We have successfully connected the objects for the «RED» component of the RGB Controller, and repeat the same for the «GREEN» and «BLUE» components as well.
Qt Designer’s Widget Editing Mode:-
The objects can be dragged from the main window’s widget box to a form, edited, resized, dragged.
The properties can be modified interactively and changes can be seen immediately.
Here to create and edit new forms first open the File menu and select New Form.
The forms can also be edited by selecting Open Form from the File menu.
Editing a Form:-
They can be moved around simply by dragging them by using the cursor keys.
Then press the Ctrl key at the same time moves the selected widget pixel by pixel.
By using the cursor keys alone make the selected widget snap to the grid when it is moved.
They can be selected by clicking the left mouse button.
As we use the Tab key to change the selection.
The widget box contains objects in a number of different categories that can be placed on the form as required.
Action |
Shortcut |
Description |
Cut |
Ctrl+X |
It will cut the selected objects to the clipboard. |
Copy |
Ctrl+C |
Also copies the selected objects to the clipboard. |
Paste |
Ctrl+V |
It will paste the objects in the clipboard onto the form. |
Delete |
Delete |
And deletes the selected objects. |
Clone object |
Ctrl+drag |
Makes a copy of the selected object or group of objects. |
Preview |
Ctrl+R |
It shows a preview of the form. |
Advantages of using qt on mobile:-
- After writing the application in Qt and c++ in result windows RT is present.
- The domain will cooperate in an easy way and problem with speed.
- The Qt is a simple library so we want to write an app for the windows and Qt.
Disadvantages of using qt on mobile:-
- There is a lack of platform which supports the problem in Qt.
- The problems occur in the mobile version but ok in desktops.
- The startup time of application is more without using the Qt compiler.