Руководство по pyqt5 для начинающих

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 из исходника, вам нужно сделать следующее:

  1. Установить SIP;
  2. Скачать исходник PyQt5;
  3. Настроить и установить.

Как вы возможно знаете, PyQt5 связывает Python с популярной библиотекой Qt, которая написана на С++.

Инструмент, который создает эту связь, называется SIP. Так что для установки PyQt5 из исходника, вам для начала нужно установить SIP.

Для установки SIP, запустите следующую команду:

sudo pip3 install pyqt5sip

Теперь вы можете загрузить и установить исходник PyQt5.

Исходники

Скачать исходник PyQt5 можно отсюда: https://www.riverbankcomputing.com/software/pyqt/download5

Руководство по PyQt5

Внимание: На момент прочтения статьи возможно появилась новая версия которая отличается от той что в скрине. Версия на текущий момент 5.11.3, вы должны самостоятельно скопировать ссылку с сайта и предоставить её в wget. Заметьте, что обновить версию придется во всех ниже предоставленных командах.

wget https://sourceforge.net/projects/pyqt/files/PyQt5/PyQt5.11.3/PyQt5_gpl5.11.3.tar.gz

tar xvzf PyQt5_gpl5.11.3.tar.gz

cd PyQt5_gpl5.11.3

Мы распаковали сжатый исходник, теперь запустите следующие команды внутри корня папки:

sudo python3 configure.py

sudo make

sudo make install

Чтобы убедиться в том, что все прошло гладко, попробуйте импортировать модуль PyQt5 так же, как мы делали все раньше. Все должно пройти хорошо.

Установка PyQt5 из исходников на Windows

Скачивайте и распакуйте архив с сайта которого мы указали выше.

Руководство по PyQt5

Так как SIP требует компилятор GCC, вам нужно установить MinGW, который является портом Windows для компилятора Linux, GCC.

Единственное, что нужно поменять — это момент конфигурации. Вам нужно сообщить Python о платформе.

Это можно выполнить следующим образом:

python configure.py platform win32g++

make

make install

Поздравляем! Вы успешно установили PyQt5 из исходника.

Установка PyQt5 Designer

Есть два способа создания GUI приложений при помощи PyQt5:

  1. Дизайн виджетов при помощи кода;
  2. Использование PyQt5 Designer.

В этом руководстве мы используем PyQt5 Designer, который упрощает процесс на столько, что вы можете выполнить большой объем работы за секунды.

Недорого заказать услуги SMM продвижения более чем в 9 социальных сетях можно на https://doctorsmm.com/. С помощью этого сервиса можно раскрутить свою группу, страницу, сообщество или канал и набрать нужное количество подписчиков, лайков, репостов и других соцсигналов.

Дизайнер PyQt5 поставляется вместе с набором инструментов. Для его установки, вам нужно установить эти инструменты.

$ pip3 install pyqt5tools

Где находится дизайнер PyQt5?

После удачной установки, вы можете найти дизайнер PyQt5 здесь:

C:Program FilesPython36Libsitepackagespyqt5tools

Кстати, если вы установили только для своего текущего пользовательского аккаунта, вы найдете дизайнер PyQt5 вот здесь:

C:UsersPythonUserAppDataLocalProgramsPythonPython3632Libsitepackages pyqt5tools

Вы можете создать короткий путь для него, вместо того, чтобы постоянно переходить к этому расположению для запуска дизайнера PyQt5.

Как использовать дизайнер PyQt5

Откройте designer.exe и увидите диалоговое окно, спрашивающее о том, какую форму шаблона вы предпочитаете.

Руководство по PyQt5

Существует пять видов доступных шаблонов:

  • Диалоговое окно с кнопками внизу (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.

Руководство по PyQt5

Далее в файловом меню (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;
  • Перетяните виджет ярлыка из бокса слева;

Руководство по PyQt5

Сохраните дизайн в файл как qlabel.ui и конвертируйте его в файл qlabel.py. Теперь поработаем с ярлыком виджета при помощи кода.

pyuic5 qlabel.ui o qlabel.py

Результат:
Руководство по PyQt5

Меняем шрифт 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())

Руководство по PyQt5

Меняем текст в 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())

Руководство по PyQt5

Именно на столько все просто! Давайте рассмотрим другие виджеты.

Виджет QLineEdit – это редактируемое поле, где вы можете принимать данные от пользователя. LineEdit содержит множество методов, с которыми можно работать.

QLineEdit PyQt5 Designer

Я создам новый дизайн 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())

Результат:

Руководство по PyQt5

  • Для 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.

QLabel QPushButton

Экспортируем 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())

Результат:

QPushButton

Замечательно!

Визуальный редактор слота/сигнала

Мы видели, как подключать сигнал виджета к слоту при помощи метода connect(), но это не единственный способ.

На самом деле, для каждого виджета есть предопределенные слоты. Вы можете связать сигнал с любым предопределенным слотом, без необходимости кодить в дизайнере PyQt5.

Перетяните QPushButton и QLineEdit в вашу форму.

Нажмите F4 и перетяните курсор из QPushButton и отпустите его в верхней части QLineEdit. Чтобы вернуться в обычный режим, нажмите на F3.

Руководство по PyQt5

Благодаря этому появится редактор сигнала/слота.

Руководство по PyQt5

Слева находятся предопределенные сигналы, справа — предопределенные слоты. Скажем, нам нужно подключить сигнал clicked() с слотом «очистки содержимого«.

Выберите сигнал clicked слева и выберите clear слот справа и нажмите OK.

Руководство по PyQt5

После выполнения подключений ваших сигналов и слотов, вы можете выйти из этого режима, нажав 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

Как выпускать сигналы в 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 в нашу форму и взглянем на её методы.

Руководство по PyQt5

Сохраняем файл как 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())

Руководство по PyQt5

Получаем все элементы из 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

Перетяните 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())

Руководство по PyQt5

Теперь вы можете писать текст вручную внутри клеток 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())

Руководство по PyQt5

Заполнение 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())

Руководство по PyQt5

  • Сначала мы создали список трех кортежей 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())

setHorizontalHeaderLabels

Таким же образом, вы можете менять заголовок ряда, при помощи метода 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())

setVerticalHeaderLabels

Как сортировать 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())

QComboBox в QTableWidget

Отлично!

Не ограничивайте себя в воображении и попробуйте вставлять различные виджеты, такие как 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())

Руководство по PyQt5

Указанный выше код будет таким же, за исключением строки, где вы создаете QСomboBox, здесь вы внесете тот виджет, который вам нужен.

Единственное ограничение — это ваше собственное воображение!

Компиляция Python приложения

Вы можете конвертировать ваши программы Python в бинарные исполняемые, и для этого имеется множество инструментов.

Лично я предпочитаю pyinstaller, который подходит для упаковки кода Python в исполняемый файл под Windows, Mac OS X, Solaris, Linux и FreeBSD. Все это будет поддерживаться 32 и 64-битной архитектурой.

Лучшая в pyinstaller для нас — это наличие полной поддержки для PyQt5.

Отлично! Для начала, установим pyinstaller:

$ pip3 install pyinstaller

После проведения установки, вы можете конвертировать программы Python следующим образом:

Ваш исполняемый файл будет создан в папке под названием dist в директории вашей программы Python.

Как вы могли догадаться, вместе с исполняемым файлом будет генерироваться множество зависимостей. Как сделать из этого один файл?

Вы можете создать один исполняемый файл. Вот так:

$ pyinstaller onefile test.py

Каждый раз, когда вы запускаете ваш исполняемый файл, будет возникать окно, как его спрятать?

Вы можете использовать флажки -w или –noconsole, чтобы спрятать окно консоли:

Эта опция доступна только для Windows и Mac OS X.

Pyinstaller предоставляет множество вариантов для упаковки вашего приложения, чтобы увидеть полный список, используйте –help:

Я старался сделать все на столько простым, на сколько это возможно. Надеюсь, это руководство оказалось для вас полезным.

Спасибо.

Являюсь администратором нескольких порталов по обучению языков программирования Python, Golang и Kotlin. В составе небольшой команды единомышленников, мы занимаемся популяризацией языков программирования на русскоязычную аудиторию. Большая часть статей была адаптирована нами на русский язык и распространяется бесплатно.

E-mail: vasile.buldumac@ati.utm.md

Образование
Universitatea Tehnică a Moldovei (utm.md)

  • 2014 — 2018 Технический Университет Молдовы, ИТ-Инженер. Тема дипломной работы «Автоматизация покупки и продажи криптовалюты используя технический анализ»
  • 2018 — 2020 Технический Университет Молдовы, Магистр, Магистерская диссертация «Идентификация человека в киберпространстве по фотографии лица»

Время на прочтение
3 мин

Количество просмотров 43K

Привет, Хабр! Сегодня я вас хочу научить делать интерфейс на Python 3&PyQt5.

Установка PyQt5

Для того, чтобы установить PyQt5 в Windows или MacOS, откройте Командную строку или Терминал и введите:

pip3 install PyQt5

Для Linux, откройте Терминал и введите:

sudo apt-get update
sudo apt-get upgrade
sudo apt-get install python3-pyqt5

Hello, World!

А сейчас сделаем Hello World приложение. Создайте файл Python, откройте его и введите такой код:

from PyQt5.QtWidgets import *
import sys


class MainWindow(QMainWindow): # главное окно
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setupUi()
    def setupUi(self):
        self.setWindowTitle("Hello, world") # заголовок окна
        self.move(300, 300) # положение окна
        self.resize(200, 200) # размер окна
        self.lbl = QLabel('Hello, world!!!', self)
        self.lbl.move(30, 30)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    win = MainWindow()
    win.show()
    sys.exit(app.exec_())

Когда вы запустите, должна получится примерно такая картина:

Окно Hello, world на Ubuntu

Окно Hello, world на Ubuntu

Меняем шрифт надписи

А теперь поменяем шрифт надписи. Теперь код станет таким:

from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
import sys


class MainWindow(QMainWindow): # главное окно
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setupUi()
    def setupUi(self):
        self.setWindowTitle("Hello, world") # заголовок окна
        self.move(300, 300) # положение окна
        self.resize(200, 200) # размер окна
        self.lbl = QLabel('Hello, world!!!', self)
        self.lbl.move(30, 30)
        self.font = QFont() # создаём объект шрифта
        self.font.setFamily("Rubik") # название шрифта
        self.font.setPointSize(12) # размер шрифта
        self.font.setUnderline(True) # подчёркивание
        self.lbl.setFont(self.font) # задаём шрифт метке


if __name__ == "__main__":
    app = QApplication(sys.argv)
    win = MainWindow()
    win.show()
    sys.exit(app.exec_())

Пример рассчитан на то, что у вас уже установлен шрифт Rubik от Google Fonts. Если нет, его всегда можно скачать отсюда.

Более продвинутая разметка с XHTML

А теперь добавим XHTML. Например, так:

from PyQt5.QtWidgets import *
import sys


class MainWindow(QMainWindow): # главное окно
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setupUi()
    def setupUi(self):
        self.setWindowTitle("Hello, world") # заголовок окна
        self.move(300, 300) # положение окна
        self.resize(200, 200) # размер окна
        self.lbl = QLabel('<i>Hello</i>, <b>world</b>!!! <s><b>123</b></s>', self)
        self.lbl.move(30, 30)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    win = MainWindow()
    win.show()
    sys.exit(app.exec_())

Те, кто хотя бы немного знают XHTML, заметят, что надпись Hello сделана курсивом, слово world — жирным, а 123 — и вычеркнуто, и жирное.

Шпаргалка по XHTML

<b>123</b>

Жирный текст

<i>123</i>

Курив

<u>123</u>

Подчёркивание

<s>123</s>

Вычёркивание

<code>123</code>

Код (моноширным шрифтом)

<sup>123</sup>

Надстрочный текст

<sub>123</sub>

Подстрочный текст

<span style=»font-size:16pt;»>123</span>

Размер текста 16 пунктов

<span style=»color:#cc0000;»>123</span>

Красный текст

<span style=» background-color:#00ff00;»>123</span>

Текст на ярко-зелёном фоне.

<span align=»center»>123</span>

Выравнивание по центру

Кстати, я знаю такой конструктор HTML. Лично мне он по душе. Только сложно вставлять свои тэги.

Больше надписей!

А теперь сделаем 2 надписи:

from PyQt5.QtWidgets import *
import sys


class MainWindow(QMainWindow): # главное окно
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setupUi()
    def setupUi(self):
        self.setWindowTitle("Hello, world") # заголовок окна
        self.move(300, 300) # положение окна
        self.resize(200, 200) # размер окна
        self.lbl = QLabel('<i>Hello</i>, <b>world</b>!!!', self)
        self.lbl.move(30, 30)
        self.lbl2 = QLabel('<u>Ещё одна метка</u>', self)
        self.lbl2.move(50, 50)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    win = MainWindow()
    win.show()
    sys.exit(app.exec_())

На вторую я тоже добавил форматирование (подчёркивание), а у первой убрал 123.

Окно без resize()

Все предыдущие примеры использовали такую конструкцию:

self.resize(200, 200)

Но без этой конструкции можно обойтись, так как виджеты будут сами себе расчищать место.

Подсказки

Ко всем виджетам можно добавить подсказку. Например (привожу только важную для понимания часть кода):

self.lbl.setToolTip('This is a <b>QLabel</b>')

Эпилог

Вот и всё. В следующей части я постараюсь описать кнопки, меню и события.

До новых встреч!

Руководство по работе с библиотекой Qt с использованием Python 3

Установка необходимых компонентов для работы

  1. Установить Python версии не менее 3.5.

    В операционных системах семейства Windows процесс установки сводится к скачиванию установщика с сайта https://www.python.org и его запуска.

    В операционных система семейства Unix процесс установки сводится к запуску пакетного менеджера с выбором необходимого пакета.

    Пример установки Python 3 в Ubuntu:

    sudo apt-get install python3
    

    По умолчанию, путь к интерпретатору Python 3 при установке на любой операционной системе добавляется к переменной среды PATH. В Windows для запуска интепретатора достаточно набрать в консоли:

    В Unix системах, как правило, может быть уже установлена более ранняя версия интерпретатора, поэтому для корректного запуска 3-ей ветки Python рекомендуется выполнить в терминале команду:

  2. В Python установка сторонних библиотек (или пакетов) происходит с помощью пакетного менеджера pip.

    По умолчанию, в Windows при установке самого интерпретатора устанвливается и пакетный менеджер.

    В Unix системах установка пакетного менеджера pip происходит отдельно.

    Пример установки pip в Ubuntu:

    sudo apt-get install python3-pip
    

    Установка сторонних пакетов (библиотек) сводится к следующей команде в терминале Unix/консоли Windows:

    pip3 install название_стороннего_пакета
    

    pip автоматически найдет, скачает и установит необходимый пакет из сети интернет.

  3. Для установки библиотеки Qt следует выполнить следующую команду:

Основы работы с Qt

Библиотека Qt является кросплатформенной и предназначена для написания графических приложений. Она инкапсулирует в себе все основные понятия любой из операционных графических систем: окна, фреймы, модальные диалоги, кнопки, текстовые поля, панели и т.д. Ядро библиотеки и всех ее компонентов написаны на языке программирования C++. Библиотека не является монолитной и разбита на несколько основных модулей, которые содержат классы для работы с графикой, сетью, файлами, аудио/видео, потоками ОС и т.д.

Пакет PyQt5 является портом для работы с Qt на языке Python. Ввиду этого, пакет наследует основные названия модулей библиотеки и их классов. Однако, в отличие от процесса работы на C++ под Qt, работа на языке Python с использованием пакета PyQt5 избавляет программиста от низкоуровневых особенностей C++ и ускоряет процесс написания программного кода. В пользу PyQt5 стоит сказать, что скорость понимания абстракций графического интерфейса, написанных на языке Python, бывает более высокой, нежели на C++.

Как правило, процесс ознакомления с PyQt5 тесно связан с чтением документации по тому или иному классу. Однако, стоит заметить, что все описания классов модулей Qt представлены на языке C++. Но такие понятия, как классы, его атрибуты и методы в языке C++ интуитивно легко перекладываются на язык Python. Тем самым, любые описания и примеры использования того или иного атрибута/метода на языке C++ в документации Qt справедливы и для Python, где любые упоминания про указатели и ссылки просто опускаются при работы с PyQt5.

На данный момент библиотека Qt развивается в двух направлениях: Qt Widgets и Qt Quick. Qt Widgets является фундаментальным и базовым направлением библиотеки. Данный модуль существует с момента сущестования платформы и направлен на создания графических приложений в стиле объектно-ориентированного подхода, где любой компонент интерфейса представлен объектом класса, тем самым организуя весть графический интерфейс пользователя в иерархию объектов. Qt Quick является более современным ответвлением платформы Qt. Данное направление вводит новые высокоуровневые абстракции вроде машины конечного автомата и вносит принципы реактивного программирования. Также, Qt Quick предлагает идею декларативного описания пользовательского интерфейса средствами JavaScript подобного языка QML.

В данном руководстве описываются базовые принципы работы с Qt Widgets совместно с пакетом PyQt5.

Ссылка на документацию Qt 5: http://doc.qt.io/qt-5/qtwidgets-index.html

Ссылка на документацию PyQt5: http://pyqt.sourceforge.net/Docs/PyQt5

1. Основной цикл обработки событий

Приложение Qt построено на основе бесконечного цикла, который обратывает события: события операционной системы, события пользоваля приложения (поведение мыши, использование клавиатуры). Для запуска минимального приложения, следует передать циклу контекст, в котором начнут обрабатываться события. Базовым контекстом является понятие Виджет, которое представлено классом QWidget.

Виджет — это аналог окна, которое как может иметь рамку, кнопки сворачивания и закрытия, а может их и не иметь. С точки зрения операционных систем, это именно контекст, где операционная система может реагировать на события пользователя. В Qt виджеты могут содержать иерархию из других виджетов. При этом, разработчик никак не ограничен тем, как будет выглядеть виджет. Им могут быть как стандартное текстовое поле, кнопка, текстовая метка, так и сложный графический объект со своим стилем прорисовки.

Минимальное приложение Qt состоит из определения класса наследника QWidget, создания его экземпляра и запуска бесконечного цикла обработки событий.

import sys
from PyQt5.QtWidgets import QWidget, QApplication, QVBoxLayout, QLabel


class MyWidget(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self._initUI()

    def _initUI(self):
        self.label = QLabel('Hello', self)

        self.layout = QVBoxLayout(self)
        self.layout.addWidget(self.label)

        self.setLayout(self.layout)
        self.setGeometry(0, 0, 100, 100)
        self.show()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    myWidget = MyWidget()
    sys.exit(app.exec_())

2. Виджеты

Как было сказано, виджет представлен классом QWidget. Для создания виджета следует определить класс-наследник QWidget. В конструкторе класса следует добавить последний аргумент по умолчанию parent и вызвать инструкцию:

Параметр parent указывает на родительский виджет описываемого. Если описываемый является корневым, parent = None. Стоит сказать, что создание любого другого дочернего виджета, разметки должно просходить с передачей последним аргументом родительского виджета parent. Наиболее часто, родителем оказывается описываемый виджет self.

Часто, виджетам устанавливают ту или иную разметку, по правилам которой внутри располагаются другие виджеты. Наиболее используемыми классами разметки являются QVBoxLayout (вертикальная разметка) и QHBoxLayout (горизонтальная разметка). Для добавления дочерних виджетов в разметку предназачен метод addWidget(QWidget). Чтобы установить виджету ту или иную разметку используется метод setLayout(QLayout).

Хорошим стилем считается создание всех дочерних разметок/виджетов описываемого в теле контструктора класса. Как правило, создается приватный метод, например _initUI, и вызывается в конструкторе __init__.

Qt предоставляет набор удобных стандартных виджетов, поведение которых также можно изменить определением нового класса-наследника.

2.1 Текстовая метка: QLabel

Пример использования:

from PyQt5.QtWidgets import QLabel

...

self.label = QLabel('Text', self)

Часто используемые методы:

  1. text() → string: возвращает текст метки.
  2. setText(string): устанавливает текст метки.

2.2 Текстовое поле: QLineEdit

Пример использования

from PyQt5.QtWidgets import QLineEdit

...

self.edit = QLineEdit('текст в поле ввода', self)

Часто используемые методы:

  1. text() → string: возвращает текст поля ввода.
  2. setText(string): устанавливает текст поля ввода.

2.3 Кнопка: QPushButton

Пример использования

from PyQt5.QtWidgets import QPushButton

...

self.button = QPushButton('Текст на кнопке', self)

Часто используемые методы:

  1. setText(string): устанавливает текст на кнопке.

2.4 Многострочное поле ввода: QTextEdit

Пример использования

from PyQt5.QtWidgets import QTextEdit

...

self.muli_edit = QTextEdit(self)

Часто используемые методы:

  1. setText(string): устанавливает текст в поле ввода.
  2. toPlainText() → string: возвращает обычный текст.
  3. toHtml() → string: возврашает текст в формате HTML.

2.5 Слайдер: QSlider

Пример использования

from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QSlider

...

self.slider = QSlider(Qt.Horizontal, self)

Часто используемые методы:

  1. setTickInterval(int): устанавливает шаг.
  2. tickInterval() → int: возвращает шаг.
  3. setMinimum(int): устанавливает минимальное значение.
  4. setMaximum(int): устанавливает максимальное значение.

2.6 Чек-бокс: QCheckBox

Пример использования

from PyQt5.QtWidgets import QCheckBox

...

self.checkbox = QCheckBox('Метка чек-бокса', self)

Часто используемые методы:

  1. toogle(): ставит/снимает чек-бокс.

3. Взаимодействие с пользователем: введение в сигналы/слоты

В библиотеке Qt любые из классов, которые являются наследниками класса QObject могут участвовать в механизме сигналов/слотов. Практически все классы Qt являются наследниками QObject, в том числе и виджеты.

Механизм сигналов/слотов — является базовым понятием в обработке событий. Событиями могут выступать: действия пользователя графического интерфейса, события операционной системы и т.д. Само понятие события в Qt носит название Сигнал. Реакция на сигнал это всегда какая-либо простая функция, которая носит название Слот.

Как правило, дочерние компоненты описываемого виджета генерируют какие-либо сигналы. Например, сигнал клика по кнопке. Для реакции на данное событие создается метод внтури описываемого виджета. Стоит упомянуть, что сигнал может передавать любую порцию информации: число, строка, список и т.д.. Если сигнал отправляет какие-либо данные, то в методе на реакцию данного сигнала должен передаваться аргумент(ы) для обработки передаваемой информации.

Пример использования механизма сигналов/слотов:

import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (QWidget, QLCDNumber, QSlider,
                             QVBoxLayout, QApplication)


class Example(QWidget):

    def __init__(self):
        super().__init__()

        self.initUI()

    def initUI(self):

        lcd = QLCDNumber(self)
        sld = QSlider(Qt.Horizontal, self)

        vbox = QVBoxLayout()
        vbox.addWidget(lcd)
        vbox.addWidget(sld)

        self.setLayout(vbox)
        sld.valueChanged.connect(lcd.display)

        self.setGeometry(300, 300, 250, 150)
        self.show()


if __name__ == '__main__':

    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

Как видно из примера, виджет sld генерирует сигнал valueChanged, информирующий об изменении позиции слайдера. В свою очередь, данный сигнал связан с методом display виджета lcd. В данном случае, valueChanged является сигналом и отсылает значение типа int, а display является методом-сигналом, в который передается значение типа int. Связывание сигнала и слота происходит с помощью метода сигнала connect, который имеется у любого сигнала Qt.

Для определения слота, следует создать метод у класса описываемого виджета и привязать нужный сигнал к новому слоту с помощью метода сигнала connect.

Пример определения слота:

import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (QWidget, QApplication, QVBoxLayout,
                             QLabel, QPushButton)


class MyWidget(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self._initUI()

    def _initUI(self):
        self.label = QLabel('Push the Button', self)
        self.button = QPushButton('Push', self)
        self.button.clicked.connect(self._handleClickButton)

        self.layout = QVBoxLayout(self)
        self.layout.addWidget(self.label)
        self.layout.addWidget(self.button)

        self.setLayout(self.layout)
        self.show()

    def _handleClickButton(self):
        self.label.setText('Push Done.')

if __name__ == '__main__':
    app = QApplication(sys.argv)
    myWidget = MyWidget()
    sys.exit(app.exec_())

Чтобы определить слот, который реагирует на сигналы, отправляющие какую-либо информацию, следует лишь добавить аргумент(ы).

Пример определения слота на сигнал, передающий значение типа int:

import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (QWidget, QApplication, QVBoxLayout,
                             QLabel, QSlider)


class MyWidget(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self._initUI()

    def _initUI(self):
        self.label = QLabel('Change Slider', self)
        self.slider = QSlider(Qt.Horizontal, self)
        self.slider.valueChanged.connect(self._handleChangeSlider)

        self.layout = QVBoxLayout(self)
        self.layout.addWidget(self.label)
        self.layout.addWidget(self.slider)

        self.setLayout(self.layout)
        self.show()

    def _handleChangeSlider(self, value):
        self.label.setText(str(value))

if __name__ == '__main__':
    app = QApplication(sys.argv)
    myWidget = MyWidget()
    sys.exit(app.exec_())

Виджет slider генерирует сигнал valueChanged при изменении слайдера. В свою очередь, данный сигнал связан с слотом/методом _handleChangeSlider, который принимает аргумент value типа int. При любом изменении слайдера вызывается метод _handleChangeSlider, который устанавливает текст метке label на значение ползунка слайдера. Стоит сказать, что метод метки label.setText принимает строковое значение, поэтому значение, отправляемое сигналом, числового типа int явно приводится к строковому типу str.

В документации библиотеки Qt к тому или иному классу виджета все сигналы находятся в секции Signals. Особое внимание стоит обращать на типы данных, которые возвращают сигналы.

В этом руководстве по PyQt5 будет показано, как использовать Python 3 и Qt для создания графического интерфейса пользователя в Windows, Mac или Linux. Мы даже расскажем, как самостоятельно написать установщик.

PyQt — это библиотека, которая позволяет использовать фреймворк Qt GUI (GUI — это графический интерфейс пользователя) в Python. Сам Qt, как известно, написан на C++. Используя его в Python, вы можете создавать приложения намного быстрее, не жертвуя при этом значительной частью производительности C++.

PyQt5 это самая последняя, пятая версия Qt. Еще можно найти в интернете случайное упоминание PyQt4, но эта версия устарела и больше не поддерживается.

Новый интересный конкурент PyQt — это Qt for Python. Она обладает практически идентичным API, но в отличие от PyQt имеет лицензию LGPL и, следовательно, может использоваться бесплатно даже в коммерческих проектах. Она поддерживается компанией Qt, а значит, скорее всего, за ней будущее. Здесь мы используем PyQt, потому что она более зрелая. Но, так как их интерфейсы очень похожи, вы всегда можете перейти на Qt for Python позднее.

Установка PyQt

Лучший способ управлять зависимостями в Python — через виртуальную среду. Виртуальная среда — это просто локальный каталог, содержащий библиотеки для данного конкретного проекта. В отличии от общесистемной установки библиотек, это не не повлияет на другие ваши проекты.

Для создания виртуальной среды в текущем каталоге выполните следующую команду:

python3 -m venv venv

Эта команда создаст директорию venv/. Чтобы активировать виртуальную среду в Windows, выполните следующую команду:

call venv/scripts/activate.bat

А для Mac и Linux вот эту:

source venv/bin/activate

То, что виртуальная среда активирована, вы можете увидеть по префиксу (venv) в командной строке:

Теперь, чтобы установить PyQt, выполните следующую команду:

pip install PyQt5==5.9.2

Мы используем версию 5.9.2, потому что не все версии PyQt одинаково стабильны. Данная версия гарантированно будет работать хорошо.

Итак, поздравляем! Вы только что успешно установили PyQt5.

Создание GUI (графического интерфейса пользователя)

Теперь самое время написать ваш первый графический интерфейс! В нашей виртуальной среде запустим Python и выполним следующие команды:

Сначала мы загружаем библиотеку PyQt при помощи оператора import:

from PyQt5.QtWidgets import QApplication, QLabel

Затем мы создаем QApplication при помощи следующей команды:

app = QApplication([])

Это обязательное требование библиотеки Qt: каждое приложение с графическим интерфейсом пользователя должно иметь ровно один экземпляр класса QApplication. До выполнения данной строки многие вещи в Qt просто не работают. Поэтому такая команда будет присутствовать в каждом вашем Qt приложении.

Скобки [] в данной команде представляют аргументы командной строки, переданные приложению. Поскольку наше приложение не использует никаких параметров, мы оставляем скобки пустыми.

Теперь, чтобы реально что-нибудь увидеть, мы создаем следующее сообщение:

label = QLabel('Hello World!')

Затем мы даем команду вывести это на экран:

label.show()

Эта команда покажет небольшое окошко (его вид зависит от вашей операционной системы):

Последний шаг — передача управления библиотеке Qt и указание «запустить приложение, пока пользователь не закроет его». Это делается так:

app.exec_()

Если все это сработало, как ожидалось, тогда супер! Вы только что создали при помощи Python и библиотеки Qt свое первое приложение с графическим интерфейсом.

Виджеты

Все, что вы видите в приложениях PyQt, называется виджетами. Кнопки, сообщения, окна, диалоговые окна, индикаторы выполнения и так далее — все это виджеты. Подобно html элементам, виджеты в Qt зачастую вложены друг в друга. Например, окно может содержать кнопку, а кнопка, в свою очередь, — сообщение.

На следующей картинке показаны наиболее распространенные виджеты Qt:

Они перечислены ниже в порядке сверху вниз и слева направо:

  • QLabel
  • QComboBox
  • QCheckBox
  • QRadioButton
  • QPushButton
  • QTableWidget
  • QLineEdit
  • QSlider
  • QProgressBar

Отсюда вы можете загрузить, если хотите, код приложения, которое создает такое окно.

Макеты

Как и в приведенном выше примере, ваш графический интерфейс, скорее всего, будет состоять из нескольких виджетов. В этом случае вам нужно указать Qt, как их расположить. Например, вы можете использовать QVBoxLayout для вертикального расположения виджетов:

Вот код, создающий интерфейс, изображенный на картинке выше:

from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QVBoxLayout

app = QApplication([])
window = QWidget()
layout = QVBoxLayout()
layout.addWidget(QPushButton('Top'))
layout.addWidget(QPushButton('Bottom'))
window.setLayout(layout)
window.show()
app.exec_() 

Как и ранее, мы создали экземляр класса QApplication. Затем мы создаем само окно (window). Мы используем для него самый простой тип QWidget, так как он просто используется как контейнер, а никакого особого поведения нам задавать не нужно. Затем мы создаем макет (layout) и добавляем к нему две кнопки QPushButton. Наконец, мы говорим окну использовать именно этот макет (и, следовательно, его содержимое). Как и в нашем первом приложении, мы заканчиваем вызовами методов .show () и app.exec_ ().

Безусловно, существует большое количество разных макетов, например QHBoxLayout для размещения элементов в ряд. Более подробно с ними можно ознакомиться в документации Qt.

Пользовательские стили

Одной из сильных сторон Qt является поддержка пользовательских стилей. Существует множество механизмов, позволяющих настраивать внешний вид вашего приложения. В этом разделе описаны некоторые из них.

Встроенные стили

Самый грубый способ изменить внешний вид вашего приложения — установить глобальный стиль. Вспомните изображение виджетов, которое мы уже приводили выше:

Здесь используется стиль под названием Fusion. Если вместо этого использовать стиль Windows, это будет выглядеть следующим образом:

Чтобы применить стиль, нужно использовать метод app.setStyle (…):

from PyQt5.QtWidgets import *
app = QApplication([])
app.setStyle('Fusion')
...

Доступные стили зависят от вашей платформы, но обычно они включают в себя «Fusion», «Windows», «WindowsVista» (только для Windows) и «Macintosh» (только для Mac).

Пользовательские цвета

Если вам нравится стиль, но вы хотите изменить его цвета (например, на темную тему), вы можете использовать QPalette и app.setPalette (...). Например:

from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPalette
from PyQt5.QtWidgets import QApplication, QPushButton

app = QApplication([])
app.setStyle('Fusion')
palette = QPalette()
palette.setColor(QPalette.ButtonText, Qt.red)
app.setPalette(palette)
button = QPushButton('Hello World')
button.show()
app.exec_() 

Это изменит цвет текста в кнопках на красный:

Как создать темную тему стиля Fusion, можно посмотреть вот здесь.

Таблицы стилей

В дополнение к вышесказанному вы можете изменить внешний вид своего приложения с помощью таблиц стилей. Это аналог CSS в Qt. Например, мы можем добавить некоторое пространство:

from PyQt5.QtWidgets import QApplication, QPushButton

app = QApplication([])
app.setStyleSheet("QPushButton { margin: 10ex; }")
button = QPushButton('Hello World')
button.show()
app.exec_() 

Для получения дополнительной информации о таблицах стилей смотрите документацию Qt.

Сигналы и слоты

Qt использует механизм, называемый сигналами (signals), чтобы вы могли реагировать на такие события, как нажатие кнопки пользователем. Следующий пример иллюстрирует это. Код содержит кнопку, при нажатии на которую отображается окно сообщения.

from PyQt5.QtWidgets import *

app = QApplication([])
button = QPushButton('Click')
def on_button_clicked():
    alert = QMessageBox()
    alert.setText('You clicked the button!')
    alert.exec_()

button.clicked.connect(on_button_clicked)
button.show()
app.exec_() 

Строка button.clicked — это сигнал, метод .connect (...) позволяет нам установить на нем так называемый слот. Это просто функция, которая вызывается при поступлении сигнала. В приведенном выше примере наш слот показывает окно сообщения.

Термин «слот» важен при использовании Qt в C++, потому что в C++ слоты должны быть объявлены особым образом. Однако в Python любая функция может быть слотом — мы видели это выше. Поэтому различие между слотами и обычными функциями не имеет для нас большого значения.

Сигналы в Qt используются повсеместно. И, конечно, вы также можете определить свои собственные сигналы. Но это выходит за рамки данного руководства.

Компилируем наше приложение

Теперь у вас есть базовые знания для создания GUI, который реагирует на ввод пользователя. Допустим, вы написали приложение. Оно работает на вашем компьютере. Как передать его другим людям, чтобы они тоже могли его запустить?

Вы можете попросить пользователей вашего приложения установить Python и PyQt, как мы сделали выше, а затем предоставить им свой исходный код. Но это очень утомительно (и обычно непрактично). Вместо этого нам нужен отдельный вариант вашего приложения. То есть двоичный исполняемый файл, который другие люди могут запускать в своих системах, не устанавливая ничего.

В мире Python процесс превращения исходного кода в автономный исполняемый файл называется замораживанием (freezing). Несмотря на наличие множества библиотек, решающих эту проблему, например PyInstaller, py2exe, cx_Freeze, bbfreze, py2app и так далее, замораживание приложений PyQt всегда было на удивление непростой проблемой.

Мы будем использовать новую библиотеку под названием fbs, которая позволяет создавать автономные исполняемые файлы для приложений PyQt. Для ее установки введите команду:

pip install fbs

Затем выполним следующую команду:

fbs startproject

Вам будет предложено ввести несколько значений:

Когда вы введете предложенную команду run, должно открыться пустое окно:

Это приложение PyQt5, такое же, как и те, что мы видели раньше. Его исходный код находится в src/main/python/main.py в вашем текущем каталоге. Но вот что самое интересное: мы можем использовать fbs, чтобы превратить его в отдельный исполняемый файл!

fbs freeze

Эта команда создает и помещает автономный двоичный файл в папку /MyApp/ вашего текущего каталога. Вы можете отправить его своим друзьям (с той же ОС, что и ваша), и они также смогут запустить ваше приложение!

Бонус: создаем установщик

Библиотека fbs также позволяет вам создать установщик для вашего приложения с помощью команды fbs installer:

(Если вы работаете в Windows, вам сначала нужно установить NSIS и поместить путь к нему в свой PATH.)

За дополнительной информацией по использованию библиотеки fbs обратитесь к ее документации.

Итоги

Если вы дошли до этого места — примите наши поздравления. Надеемся, теперь у вас есть хорошее представление о том, как для написания приложений Python можно использовать PyQt (и различные ее части). Мы также узнали, как можно создавать автономные исполняемые файлы и установщики при помощи fbs.

Я начинаю перевод серии уроков PyQt5 от zetcode.

PyQt5 — это набор Python библиотек для создания графического интерфейса на базе платформы Qt5 от компании Digia.

Он доступен для Python 2.x и 3.x. Этот учебник использует Python 3.

Библиотека Qt является одной из самых мощных библиотек GUI (графического интерфейса пользователя).

Установить PyQt5 на Windows можно с официального сайта библиотеки.

Установить PyQt5 на linux-системы можно с помощью любого менеджера пакетов:

sudo apt-get install python3-pyqt5 pyqt5-dev-tools

PyQt5 реализован в виде набора python-модулей. Эта библиотека имеет более 620 классов и 6000 функций и методов.

Это мультиплатформенная библиотека, которая работает на всех основных операционных системах, в том числе Unix, Windows и Mac OS.

Простой пример

Это простой пример, показывающий небольшое окно. Тем не менее, мы можем многое сделать с этим окном. Мы можем изменить его размер, развернуть его или свернуть. Это требует написания значительного объёма кода. Однако кто-то уже запрограммировал эту функциональность до нас. Поскольку эта функциональность повторяется в большинстве приложений, нет необходимости писать её снова.

PyQt5 является инструментом высокого уровня. Если бы мы писали это на более низком уровне, следующий пример кода легко мог бы растянуться на сотни строк:

#!/usr/bin/python3
# -*- coding: utf-8 -*-

import sys
from PyQt5.QtWidgets import QApplication, QWidget


if __name__ == '__main__':

    app = QApplication(sys.argv)

    w = QWidget()
    w.resize(250, 150)
    w.move(300, 300)
    w.setWindowTitle('Simple')
    w.show()

    sys.exit(app.exec_())

Приведенный выше код показывает небольшое окно на экране.

import sys
from PyQt5.QtWidgets import QApplication, QWidget

Здесь мы делаем необходимые импорты. Основные виджеты расположены в PyQt5.QtWidgets.

app = QApplication(sys.argv)

Каждое приложение PyQt5 должно создать объект приложения (экземпляр QApplication). Параметр sys.argv это список аргументов командной строки. Скрипты Python можно запускать из командной строки. Это способ, которым мы можем контролировать запуск наших сценариев.

w = QWidget()

Виджет QWidget это базовый класс для всех объектов интерфейса пользователя в PyQt5. Мы предоставляем конструктор по умолчанию для QWidget. Конструктор по умолчанию не имеет родителя. Виджет без родителей называется окно.

w.resize(250, 150)

Метод resize() изменяет размеры виджета. Он стал 250 пикселей в ширину и 150 в высоту.

w.move(300, 300)

Метод move() двигает виджет на экране на координату x=300, y=300.

w.setWindowTitle('Simple')

Здесь мы задаём заголовок нашего окна.

w.show()

Метод show() отображает виджет на экране. Виджет сначала создаётся в памяти, и только потом (с помощью метода show) показывается на экране.

sys.exit(app.exec_())

Наконец, мы попадаем в основной цикл приложения. Обработка событий начинается с этой точки. Основной цикл получает события от оконной системы и распределяет их по виджетам приложения. Основной цикл заканчивается, если мы вызываем метод exit() или главный виджет уничтожен. Метод sys.exit() гарантирует чистый выход. Вы будете проинформированы, как завершилось приложение.

Метод exec_ () имеет подчеркивание. Это происходит потому, что exec является ключевым словом в python 2.

Simple

Значок приложения

Значок приложения — небольшое изображение, которое обычно отображается в верхнем левом углу заголовка. В следующем примере мы покажем, как сделать это в PyQt5. Мы также представим некоторые новые методы.

Не забудьте также скачать какую-нибудь иконку :)

#!/usr/bin/python3
# -*- coding: utf-8 -*-

import sys
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtGui import QIcon


class Example(QWidget):

    def __init__(self):
        super().__init__()

        self.initUI()


    def initUI(self):

        self.setGeometry(300, 300, 300, 220)
        self.setWindowTitle('Icon')
        self.setWindowIcon(QIcon('web.png'))

        self.show()


if __name__ == '__main__':

    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

Предыдущий пример был написан в процедурном стиле. Язык программирования Python поддерживает как процедурный, так и объектно-ориентированный стили программирования. Программирование в PyQt5 означает программирование в ООП.

class Example(QWidget):

    def __init__(self):
        super().__init__()
        ...

Три важные вещи в объектно-ориентированном программировании это классы, данные и методы. Здесь мы создаем новый класс Example. Класс Example наследуется от класса QWidget. Это означает, что мы вызываем два конструктора: первый для класса Example и второй для родительского класса. Функция super() возвращает родительский объект Example с классом, и мы вызываем его конструктор.

self.initUI()

Создание GUI делегируется методу initUI().

self.setGeometry(300, 300, 300, 220)
self.setWindowTitle('Icon')
self.setWindowIcon(QIcon('web.png'))

Все три метода были унаследованы от класса QWidget.

Метод setGeometry() делает две вещи: помещает окно на экране и устанавливает его размер. Первые два параметра х и у — это позиция окна. Третий — ширина, и четвертый — высота окна. На самом деле, он сочетает в себе методы resize() и move() в одном методе.

Последний метод устанавливает иконку приложения. Чтобы сделать это, мы создали объект QIcon. QIcon получает путь к нашей иконке для отображения.

if __name__ == '__main__':

    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

Создаются объекты application и Example. Запускается основной цикл.

Icon

Подсказки

Мы можем предоставить всплывающую подсказку для любого из виджетов.

#!/usr/bin/python3
# -*- coding: utf-8 -*-

import sys
from PyQt5.QtWidgets import (QWidget, QToolTip,
    QPushButton, QApplication)
from PyQt5.QtGui import QFont


class Example(QWidget):

    def __init__(self):
        super().__init__()

        self.initUI()


    def initUI(self):

        QToolTip.setFont(QFont('SansSerif', 10))

        self.setToolTip('This is a <b>QWidget</b> widget')

        btn = QPushButton('Button', self)
        btn.setToolTip('This is a <b>QPushButton</b> widget')
        btn.resize(btn.sizeHint())
        btn.move(50, 50)

        self.setGeometry(300, 300, 300, 200)
        self.setWindowTitle('Tooltips')
        self.show()


if __name__ == '__main__':

    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

В этом примере мы покажем подсказку для двух виджетов PyQt5.

QToolTip.setFont(QFont('SansSerif', 10))

Этот статический метод устанавливает шрифт, используемый для отображения подсказки. Мы используем шрифт 10px SansSerif.

self.setToolTip('This is a <b>QWidget</b> widget')

Чтобы создать всплывающую подсказку, мы вызываем метод setToolTip(). Мы можем использовать форматирование текста.

btn = QPushButton('Button', self)
btn.setToolTip('This is a <b>QPushButton</b> widget')

Мы создаем виджет кнопки и устанавливаем подсказку для него.

btn.resize(btn.sizeHint())
btn.move(50, 50)

Меняем размер кнопки и перемещаем относительно окна. Метод sizeHint() дает рекомендуемый размер для кнопки.

Tooltips

Закрытие окна

Очевидный способ закрыть окно, это нажать на крестик. В следующем примере мы покажем, как мы можем программно закрыть наше окно. Мы кратко рассмотрим сигналы и слоты.

#!/usr/bin/python3
# -*- coding: utf-8 -*-

import sys
from PyQt5.QtWidgets import QWidget, QPushButton, QApplication
from PyQt5.QtCore import QCoreApplication


class Example(QWidget):

    def __init__(self):
        super().__init__()

        self.initUI()


    def initUI(self):

        qbtn = QPushButton('Quit', self)
        qbtn.clicked.connect(QCoreApplication.instance().quit)
        qbtn.resize(qbtn.sizeHint())
        qbtn.move(50, 50)

        self.setGeometry(300, 300, 250, 150)
        self.setWindowTitle('Quit button')
        self.show()


if __name__ == '__main__':

    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

В этом примере, мы создаем кнопку выхода. После нажатия на кнопку, приложение завершается.

qbtn = QPushButton('Quit', self)

Мы создаем кнопку. Кнопка является экземпляром класса QPushButton. Первый параметр конструктора — название кнопки. Вторым параметром является родительский виджет. Родительский виджет является виджетом Example, который наследуется от QWidget.

qbtn.clicked.connect(QCoreApplication.instance().quit)

Система обработки событий в PyQt5 построена на механизме сигналов и слотов. Если мы нажмем на кнопку, вызовется сигнал «нажатие». Слот может быть слот Qt или любая Python функция.

QCoreApplication содержит главный цикл обработки; он обрабатывает и диспетчеризирует все события. Метод instance() дает нам его текущий экземпляр.

Обратите внимание, что QCoreApplication создается с QApplication. Сигнал «нажатие» подключен к методу quit(), который завершает приложение. Коммуникация осуществляется между двумя объектами: отправителя и приемника. Отправитель кнопка, приемник — объект приложения.

Quit button

Message Box

По умолчанию, если мы нажмем на крестик, QWidget закрывается. Иногда мы хотим изменить это поведение по умолчанию, например, если у нас есть открытый файл, в котором мы сделали некоторые изменения. Мы показываем окно с сообщением для подтверждения действия.

#!/usr/bin/python3
# -*- coding: utf-8 -*-

import sys
from PyQt5.QtWidgets import QWidget, QMessageBox, QApplication


class Example(QWidget):

    def __init__(self):
        super().__init__()

        self.initUI()


    def initUI(self):

        self.setGeometry(300, 300, 250, 150)
        self.setWindowTitle('Message box')
        self.show()


    def closeEvent(self, event):

        reply = QMessageBox.question(self, 'Message',
            "Are you sure to quit?", QMessageBox.Yes |
            QMessageBox.No, QMessageBox.No)

        if reply == QMessageBox.Yes:
            event.accept()
        else:
            event.ignore()


if __name__ == '__main__':

    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

Если мы закрываем QWidget, генерируется QCloseEvent. Чтобы изменить поведение виджета, нам нужно переопределить обработчик события closeEvent().

reply = QMessageBox.question(self, 'Message',
    "Are you sure to quit?", QMessageBox.Yes |
    QMessageBox.No, QMessageBox.No)

Мы показываем окно с сообщением и с двумя кнопками: Yes и No. Первая строка отображается в заголовке окна. Вторая строка является текстовым сообщением и отображается в диалоговом окне. Третий аргумент определяет комбинацию кнопок, появляющихся в диалоге. Последний параметр — кнопка по умолчанию. Это кнопка, на которой изначально установлен фокус клавиатуры. Возвращаемое значение хранится в переменной reply.

if reply == QtGui.QMessageBox.Yes:
    event.accept()
else:
    event.ignore()

Здесь мы проверяем возвращаемое значение. Если мы нажмем на кнопку Yes, мы принимаем событие, которое приводит к закрытию виджета и приложения. В противном случае мы будем игнорировать событие закрытия.

Message box

Центрирование окна на экране

Следующий скрипт показывает, как мы можем центрировать окно на рабочем столе.

#!/usr/bin/python3
# -*- coding: utf-8 -*-

import sys
from PyQt5.QtWidgets import QWidget, QDesktopWidget, QApplication


class Example(QWidget):

    def __init__(self):
        super().__init__()

        self.initUI()


    def initUI(self):

        self.resize(250, 150)
        self.center()

        self.setWindowTitle('Center')
        self.show()


    def center(self):

        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())


if __name__ == '__main__':

    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

Класс QtWidgets.QDesktopWidget предоставляет информацию о компьютере пользователя, в том числе о размерах экрана.

self.center()

Код, который будет центрировать окно, находится в нами созданном методе center().

qr = self.frameGeometry()

Мы получаем прямоугольник, определяющий геометрию главного окна. Это включает в себя любые рамки окна.

cp = QDesktopWidget().availableGeometry().center()

Мы получаем разрешение экрана нашего монитора. И с этим разрешением, мы получаем центральную точку.

qr.moveCenter(cp)

Наш прямоугольник уже имеет ширину и высоту. Теперь мы установили центр прямоугольника в центре экрана. Размер прямоугольника не изменяется.

self.move(qr.topLeft())

Мы двигаем верхний левый угол окна приложения в верхний левый угол прямоугольника qr, таким образом, центрируя окно на нашем экране.

В этой части урока PyQt5 мы рассмотрели некоторые основы.

Для вставки кода на Python в комментарий заключайте его в теги <pre><code class=»python3″>Ваш код</code></pre>

Понравилась статья? Поделить с друзьями:
  • Мануалов нет тойота ярис
  • Руководство по эксплуатации бмв х5 g05
  • Посудомоечная машина bosch electronic aquastop встраиваемая инструкция
  • Венецианская штукатурка под мрамор своими руками пошаговая инструкция с фото
  • Обмен валюты в банкомате альфа банка без карты инструкция