551.57K
Category: programmingprogramming

Введение в PyQt5

1.

PyQt5

2.

Введение в PyQt5

3.

Что такое PyQt5?
• PyQt5 является одним из наиболее популярным модулей для создания GUI приложений в
Python.
• PyQt5 реализован как комплект Python-модулей. Он включает в себя около 620 классов и 6000
функций и методов. Это мульти-платформенный инструментарий, который запускается на
большинстве операционных систем, среди которых Unix, Windows и MacOS. PyQt5 реализован
под двумя лицензиями. Разработчики могут выбрать между GPL и коммерческой лицензией.

4.

Установка PyQt5

5.

Установка PyQt5
•pip install PyQt5

6.

Содержимое PyQt5

7.

Модули PyQt5
QtCore
QtGui
QtWidgets
QtMultimedia
QtBluetooth
QtNetwork
QtPositioning
Enginio
QtWebSockets
QtWebKit
QtWebKitWidgets
QtXml
QtSvg
QtSql
QtTest

8.

Модули PyQt5
• - Модуль QtCore содержит ядро с неграфической функциональностью. Этот модуль используется
для работы с временем, файлами, папками, различными типами файлов, потоками, адресами
URL, MIME-типами и процессами.
• - QtGui содержит классы для интеграции систем окон, обработки событий, 2D-графики, базовой
обработки изображений, шрифтов и текста.
• - Модуль QtWidgets содержит классы, которые обеспечивают набор UI-элементов для создания
классических пользовательских интерфейсов.
• - QtMultimedia содержит классы для управления мультимедиа-содержимым, а также API для
доступа к камере или функциональности радио.
• - Модуль QtBluetooth содержит классы для поиска устройств, соединения и взаимодействия с
ними.
• - Модуль QtNetwork содержит классы для сетевого программирования. Эти классы облегчают
работу с клиентами и серверами TCP/IP и UDP, делая сетевое программирование более легким
и адаптивным.
• - QtPositioning содержит классы для определения местоположения с использованием
всевозможных источников, таких как спутники, Wi-Fi или текстовые файлы.

9.

Модули PyQt5
• - Модуль Enginio реализует клиентскую библиотеку для организации доступа к облачным
сервисам Qt – Manaded Application Runtime.
• - Модуль QtWebSockets содержит классы, которые реализуют протокол WebSocket.
• - QtWebKit содержит классы для реализации веб-браузера, основанного на библиотеке WebKit2.
• - Модуль QtWebKitWidgets содержит классы для WebKit1, основанные на реализации веб-
браузера, для использования в приложениях, базирующихся на QtWidgets.
• - QtXml содержит классы для работы с XML файлами. Этот модуль предоставляет реализацию
сразу для двух API: SAX и DOM.
• - Модуль QtSvg содержит классы для отображения содержимого SVG-файлов. Scalable Vector
Graphics (SVG) – это язык для описания двумерной графики и графических приложений в XML.
• - Модуль QtSql предоставляет классы для работы с базами данных.
• - QtTest содержит функции, которые дают возможность модульного тестирования PyQt-
приложений.

10.

Первые программы
PyQt5

11.

Пустое окно
• Этот простой пример выводит маленькое окно. Мы можем делать множество вещей с этим окном. Мы
можем менять его размер, раскрывать на весь экран или свернуть в панель задач. Это потребовало бы
много программного кода. Кто-то уже запрограммировал эту функциональность. Поскольку это
повторяется в большинстве приложений, нет необходимости программировать это с самого начала.
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_())

12.

Пустое окно
• В зависимости от системы окно может выглядеть различно, кроссплатформенность!

13.

if __name__ == "__main__"
• Достаточно часто скрипт может выполняться и самостоятельно, и может быть импортирован как модуль
другим скриптом. Так как импорт скрипта запускает этот скрипт, часто надо указать, что какие-то строки
не должны выполняться при импорте.
• В Python есть специальный прием, который позволяет указать, что какой-то код не должен
выполняться при импорте: все строки, которые находятся в блоке if __name__ == '__main__' не
выполняются при импорте.
• Переменная __name__ - это специальная переменная, которая будет равна "__main__", только
если файл запускается как основная программа, и выставляется равной имени модуля при
импорте модуля. То есть, условие if __name__ == '__main__' проверяет, был ли файл запущен
напрямую.
if __name__ == '__main__':

14.

Импорт и объект приложения
• Здесь мы обеспечили необходимый импорт модулей. Основные виджеты расположены в модуле
PyQt5.QtWidgets.
import sys
from PyQt5.QtWidgets import QApplication, QWidget
• Каждое приложение PyQt5 должно создать объект приложения. Параметр sys.argv - это список
аргументов из командной строки. Скрипты Python могут быть запущены из программной оболочки. Это
один из способов, как мы можем контролировать запуск наших скриптов.
app = QApplication(sys.argv)
• Но это не обязательно, приложение запустится и с пустым списком аргументов внутри:
app = QApplication([])

15.

Создание окна и размеры
• Виджет QWidget – это основной класс всех объектов пользовательского интерфейса в PyQt5. Мы
обеспечиваем конструктор по умолчанию для QWidget. Конструктор по умолчанию не имеет родителя.
Виджет без родителя называется окном.
w = QWidget()
• Метод resize() изменяет размер виджета. Здесь задана ширина 250px и высота 150px.
w.resize(250, 150)

16.

Параметры окна
• Метод move() перемещает виджет на позицию с координатами x=300 и y=300 на экране.
w.move(300, 300)
• Здесь мы устанавливаем название нашего окна. Оно показывается в строке заголовка.
w.setWindowTitle('Simpl
e')

17.

Показ окна и зацикливание
• Метод show() отображает виджет на экране. Виджет сначала создаётся в памяти и позже показывается на
экране.
w.show()
• Наконец, мы входим в главный цикл приложения. Обработка событий начинается в этой точке. Главный
цикл получает события из системы и отправляет их виджетам приложения. Цикл завершается, если мы
вызываем метод exit() или главное окно было закрыто. Метод sys.exit() гарантирует чистый выход. Среда
будет проинформирована, когда приложение завершится.
• Метод exec_() содержит нижнее подчеркивание, потому что exec – уже используемое имя в Python. И,
соответственно, имя exec_() было использовано взамен.
sys.exit(app.exec_())

18.

Цикл приложения
• При каждом взаимодействии с приложением — будь то нажатие клавиши, щелчок или движение мыши
— генерируется событие, которое помещается в очередь событий. В цикле событий очередь проверяется
на каждой итерации: если найдено ожидающее событие, оно вместе с управлением передаётся
определённому обработчику этого события. Последний обрабатывает его, затем возвращает управление
в цикл событий и ждёт новых событий. Для каждого приложения выполняется только один цикл событий.
• Класс QApplication содержит цикл событий Qt (нужен один экземпляр QApplication). Приложение ждёт в
цикле событий новое событие, которое будет сгенерировано при выполнении действия. Всегда
выполняется только один цикл событий.

19.

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

20.

Центрирование окна
• Нижеследующий скрипт показывает, как мы можем центрировать окно экране.
• Код, который будет центрировать окно, размещён в специальном методе center().
def center(self):
qr = self.frameGeometry()
cp = QDesktopWidget().availableGeometry().center()
qr.moveCenter(cp)
self.move(qr.topLeft())

21.

Центрирование окна
• Мы получаем прямоугольник, точно определяющий форму главного окна.
qr = self.frameGeometry()
• Класс QtGui.QDesktopWidget предоставляет информацию о пользовательском рабочем столе, включая
размер экрана.
• Мы выясняем разрешение экрана нашего монитора. Из этого разрешения, мы получаем центральную
точку.
cp =
QDesktopWidget().availableGeometry().center()

22.

Центрирование окна
• Наш прямоугольник уже имеет высоту и ширину. Теперь мы устанавливаем центр прямоугольника в
центр экрана. Размер прямоугольника не изменяется.
qr.moveCenter(cp)
• Мы перемещаем верхнюю левую точку окна приложения в верхнюю левую точку прямоугольника qr,
таким образом центрируя окно на нашем экране.
self.move(qr.topLeft())

23.

Иконка приложения
PyQt5

24.

Иконка приложения
• Иконка приложения – это маленькое изображение, которое обычно отображается в верхнем левом углу
строки заголовка. В следующем примере мы увидим, как сделать её в PyQt5. Мы также познакомимся с
несколькими новыми методами.
• Предыдущий пример был написан в процедурном стиле. Язык программирования Python поддерживает
и процедурный, и объектно-ориентированный стиль программирования. Программирование в PyQt5
означает объектно-ориентированное программирование (ООП).

25.

Иконка приложения
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_())

26.

Иконка приложения
• Есть три важных вещи в объектно-ориентированном программировании – это классы, данные и методы.
Здесь мы создаём новый класс с именем Example. Класс Example наследуется из класса QWidget. Это
значит, что мы вызываем два конструктора: первый для класса Example и второй для унаследованного
класса. Метод super() возвращает объект родителя класса Example и мы вызываем его конструктор. Метод
__init__() – это конструктор класса в языке Python.
class Example(QWidget):
def __init__(self):
super().__init__()

27.

Иконка приложения
• Создание GUI поручено методу initUI(), т.е. в этом методе будет создаваться наш интерфейс, а вызывать
его мы будем в конструкторе нашего класса
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()

28.

Иконка приложения
• Все три метода были унаследованы из класса QWidget. setGeometry делает две вещи: он определяет место
окна на экране и устанавливает его размер. Первые два параметра – позиции x и y нашего окна. Третий –
ширина, и четвёртый – высота окна. Фактически, setGeometry сочетает методы resize() и move() в одном.
Последний метод устанавливает иконку приложения. Чтобы сделать это, мы создали объект
QIcon. QIcon принимает путь к нашей иконке для её отображения.
def initUI(self):
self.setGeometry(300, 300, 300, 220)
self.setWindowTitle('Icon')
self.setWindowIcon(QIcon('web.png'))
self.show()

29.

Иконка приложения
• Приложение и объекты примера созданы. Главный цикл запущен. Приложение начинает отображаться.
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())

30.

Виджеты в PyQt5

31.

Виджеты
• Виджеты - это основные строительные блоки приложения. PyQt5 имеет широкий ряд
различных виджетов, включая кнопки, флажки, ползунки или списки. Опишем несколько
полезных виджетов: QPushButton и Qlabel
• QLabel - Создает текст, в вашем окне
• QPushButton - Создает обычную кнопку, вашем окне.
self.label1 = QLabel("Текст",
self)
self.PushButton2 = QPushButton("BTN", self)

32.

Изменение размеров
• Сейчас размер окна можно свободно поменять: щёлкните мышью на любой угол и
перетаскивайте, меняя таким образом размер. Можно дать возможность пользователям
самим менять размер приложений, а можно установить ограничения на минимальные или
максимальные размеры или фиксированный размер окна.
• В Qt размеры определяются с помощью объекта QSize. Он принимает параметры ширины и
высоты. Например, так создаётся окно фиксированного размера 400 x 300 пикселей:
self.setFixedSize(QSize(400, 300))
• Кроме .setFixedSize() можно также вызвать .setMinimumSize() и .setMaximumSize(),
чтобы установить минимальный и максимальный размеры соответственно. Попробуйте
сами! Эти методы регулирования размеров работают в любом виджете.

33.

Размещение
• Есть несколько способов размещения виджетов на экране, пока мы будем использовать самый
простой – Абсолютное позиционирование
• Мы используем метод move(), чтобы разместить наши виджеты. В этом случае ими являются
метки (labels). Мы размещаем их путём предоставления координат x и y. Начало координатной
системы – левый верхний угол. Значения x возрастают слева направо. Значения y растут сверху
вниз
lbl3 = QLabel('for programmers', self)
lbl3.move(55, 70)
Виджет метки расположен в x=55 и y=70.

34.

Подсказки PyQt5

35.

Подсказки PyQt5
• Мы можем обеспечить любой из наших виджетов всплывающей подсказкой.
import sys
from PyQt5.QtGui import QFont
from PyQt5.QtWidgets import QApplication, QWidget, QToolTip, QPushButton
class MainWindwow(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.resize(250, 150)
self.move(300, 300)
self.setWindowTitle('Simple')
if __name__ == '__main__':
app = QApplication([])
w = MainWindwow()
w.show()
sys.exit(app.exec_())

36.

Подсказки PyQt5
• Структура приложения похожа на предыдущий пример, весь UI создается в отдельной функции, но
добавляются новые инструменты.
• Этот статический метод устанавливает шрифт, используемый для показа всплывающих подсказок. Мы
используем шрифт 10px SansSerif.
QToolTip.setFont(QFont('SansSerif',
10))
• Для использования новых методов понадобится их импортировать
from PyQt5.QtGui import QFont
from PyQt5.QtWidgets import QApplication, QWidget, QToolTip,
QPushButton

37.

Подсказки PyQt5
• Чтобы создать подсказку, мы вызываем метод setTooltip(). Мы можем использовать HTML форматирование
текста.
self.setToolTip('This is a <b>QWidget</b>
widget')
• Мы создаём виджет кнопки с помощью класса QPushButton
и устанавливаем всплывающую подсказку
для неё.
btn = QPushButton('Button', self)
btn.setToolTip('This is a <b>QPushButton</b> widget')

38.

Подсказки PyQt5
• Меняем размер у кнопки, перемещаем её в окно. Метод sizeHint() даёт рекомендуемый размер для
кнопки.
btn.resize(btn.sizeHint())
btn.move(50, 50)
• И получаем результат:

39.

Задания
• Попробуйте повторить такое окно:

40.

Задания
• Попробуйте повторить такое окно:

41.

Задания
• Попробуйте повторить такое окно:

42.

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

43.

Сигналы
• Ранее мы рассмотрели классы QApplication и QMainWindow, цикл событий и добавили в окно простой
виджет. А теперь изучим механизмы Qt для взаимодействия виджетов и окон друг с другом. В статью
внесены изменения, связанные с PyQt6.
• Мы создали окно и добавили в него простой виджет push button, но кнопка пока бесполезна. Нужно
связать действие нажатия кнопки с происходящим. В Qt это делается с помощью сигналов и слотов или
событий.
• Сигналы — это уведомления, отправляемые виджетами, когда что-то происходит. Этим «чем-то» может
быть что угодно — нажатие кнопки, изменение текста в поле ввода или изменение текста в окне. Многие
сигналы инициируются в ответ на действия пользователя, но не только: в сигналах могут отправляться
данные с дополнительным контекстом произошедшего.
• Можно также писать собственные сигналы, их мы рассмотрим позже.

44.

Слоты
• Слоты в Qt — это приёмники сигналов. Слотом в приложении на Python можно сделать любую функцию
(или метод), просто подключив к нему сигнал. Принимающая функция получает данные, отправляемые
ей в сигнале. У многих виджетов Qt есть встроенные слоты, а значит, виджеты можно подключать друг к
другу напрямую.
• Рассмотрим основные сигналы Qt и их использование для подключения виджетов в приложениях.

45.

Сигналы QPushButton
• Сейчас у нас есть QMainWindow с центральным виджетом QPushButton. Подключим эту кнопку к
пользовательскому методу Python. Создадим простой настраиваемый слот the_button_was_clicked,
принимающий сигнал clicked от QPushButton:
import sys
from PyQt6.QtWidgets import QApplication, QMainWindow, QPushButton
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("My App")
button = QPushButton("Press Me!", self)
button.setCheckable(True)
button.clicked.connect(self.the_button_was_clicked)
def the_button_was_clicked(self):
print("Clicked!")
app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec()

46.

Сигналы QPushButton
• Запускаем. Если нажать на кнопку, в консоли появится текст Clicked! («Нажата!»):

47.

Получение данных
• В сигналах может отправляться дополнительная информация о произошедшем. И сигнал .clicked — не
исключение: с его помощью сообщается о нажатом (или переключенном) состоянии кнопки. Для
обычных кнопок это значение всегда False, поэтому первый слот проигнорировал эти данные. Включим
возможность нажатия кнопки, чтобы увидеть этот эффект. Ниже добавляется второй слот и выводится
состояние нажатия:
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("My App")
button = QPushButton("Press Me!", self)
button.setCheckable(True)
button.clicked.connect(self.the_button_was_clicked)
button.clicked.connect(self.the_button_was_toggled)
def the_button_was_clicked(self):
print("Clicked!")
def the_button_was_toggled(self, checked):
print("Checked?", checked)

48.

Получение данных
• Запускаем! Если нажать на кнопку, она подсветится и станет checked («Нажатой»). Чтобы отключить её,
нажимаем ещё раз. Найдите состояние нажатия в консоли:
• К сигналу подключается сколько угодно слотов, в которых можно реагировать сразу на несколько версий
сигналов.

49.

Хранение данных
• Текущее состояние виджета на Python часто хранят в переменной, что позволяет работать со значениями
без доступа к исходному виджету. Причём для их хранения используются отдельные переменные или
словарь. В следующем примере сохраняем значение кнопки checked («Нажата») в переменной
button_is_checked в self:
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.button_is_checked = True
self.setWindowTitle("My App")
button = QPushButton("Press Me!", self)
button.setCheckable(True)
button.clicked.connect(self.the_button_was_toggled)
button.setChecked(self.button_is_checked)
def the_button_was_toggled(self, checked):
self.button_is_checked = checked
print(self.button_is_checked)

50.

Хранение данных
• Сначала устанавливаем переменной значение по умолчанию True, а затем используем это значение,
чтобы установить исходное состояние виджета. Когда состояние виджета меняется, получаем сигнал и
соответственно обновляем переменную.
• Эта же схема применима к любым виджетам PyQt. Если в виджете нет сигнала, которым отправляется
текущее состояние, нужно получить значение из виджета прямо в обработчике. Например, здесь мы
проверяем состояние checked («Нажата») в нажатом обработчике:
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.button_is_checked = True
self.setWindowTitle("My App")
self.button = QPushButton("Press Me!",self)
self.button.setCheckable(True)
self.button.released.connect(self.the_button_was_released)
self.button.setChecked(self.button_is_checked)
def the_button_was_released(self):
self.button_is_checked = self.button.isChecked()
print(self.button_is_checked)

51.

Хранение данных
• Сохраним ссылку на кнопку в self, чтобы получить к ней доступ в слоте.
• Сигнал released срабатывает, когда кнопка отпускается, при этом состояние нажатия не отправляется. Его
получают из кнопки в обработчике, используя .isChecked().
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.button_is_checked = True
self.setWindowTitle("My App")
self.button = QPushButton("Press Me!",self)
self.button.setCheckable(True)
self.button.released.connect(self.the_button_was_released)
self.button.setChecked(self.button_is_checked)
def the_button_was_released(self):
self.button_is_checked = self.button.isChecked()
print(self.button_is_checked)

52.

Изменение
интерфейса

53.

Изменение интерфейса
• Мы уже видели, как принимаются сигналы и выводятся на консоль результаты. Но что происходит с
интерфейсом, когда нажимают на кнопку? Обновим метод слота, чтобы изменить кнопку, поменяв текст,
отключив её и сделав её недоступной. И отключим пока состояние, допускающее нажатие:
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("My App")
self.button = QPushButton("Press Me!", self)
self.button.clicked.connect(self.the_button_was_clicked)
def the_button_was_clicked(self):
self.button.setText("Already clicked")
self.button.setEnabled(False)
# Также меняем заголовок окна.
self.setWindowTitle("My Oneshot App")

54.

Задания
• Сделайте приложение, которое по нажатию кнопки будет выводить случайное число в консоль

55.

Задания
• Сделайте приложение, которое по нажатию кнопки будет выводить случайное число в окно

56.

Отправитель
события

57.

Отправитель события
• Иногда удобно знать, какой виджет является отправителем сигнала. Для этого, PyQt5 имеет
метод sender().
• Мы имеем две кнопки в нашем примере. В методе buttonClicked() мы определяем, какую кнопку мы
нажали, с помощью метода sender().
def buttonClicked(self):
sender = self.sender()
self.statusBar().showMessage(sender.text() + ' was pressed')

58.

Отправитель события
• Обе кнопки подключены к одному слоту.
• Мы определяем источник сигнала путём вызова метода sender(). В строке состояния приложения, мы
показываем метку нажатой кнопки.
btn1 = QPushButton("Button 1", self)
btn1.move(30, 50)
btn2 = QPushButton("Button 2", self)
btn2.move(150, 50)
btn1.clicked.connect(self.buttonClicked)
btn2.clicked.connect(self.buttonClicked)

59.

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

60.

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

61.

Меню и панели
инструментов

62.

Меню и панели инструментов
• Меню – это группа команд, располагающаяся ниже строки заголовка программы. Панель инструментов
содержит кнопки с несколькими распространенными командами в приложении.
• Основное окно
Класс QMainWindow предоставляет главное окно приложения. Он позволяет создать классический каркас
приложения со строкой состояния, панелями инструментов и меню.
• Строка состояния – это виджет, который используется для отображения сведений о состоянии.
• Строку состояния создают с помощью виджета QMainWindow.

63.

Строка состояния
• Чтобы получить строку состояния, мы вызываем метод statusBar() класса QtGui.QMainWindow. Первый
вызов метода создаёт строку состояния. Последующие вызовы возвращают объект строки
состояния. showMessage() отображает сообщение в строке состояния.
self.statusBar().showMessage('Rea
dy')

64.

Меню программы
• Строка меню – это распространенная часть приложений с графическим интерфейсом (GUI).
• Мы создаём строку меню с одним набором команд. Этот набор команд будет содержать одно действие,
завершающее приложение при его выборе. Строка состояния тоже создаётся. Действие доступно
с горячей клавишей Ctrl+Q.
• QAction – это абстракция для действий, выполняемых из меню, панелью инструментов или с
использованием горячей клавишей. В приведённых выше трёх строках, мы создаём действие с
определённой иконкой и меткой «Exit». Кроме того, для этого действия определена горячая клавиша.
Третья строка создаёт подсказку, которая показывается в строке состояния, когда мы наводим курсор
мыши на пункт меню.
exitAction = QAction(QIcon('exit.png'), '&Exit', self)
exitAction.setShortcut('Ctrl+Q')
exitAction.setStatusTip('Exit application')

65.

Меню программы
• Когда мы выбираем конкретное действие, срабатывает инициирующий сигнал. Сигнал присоединяют
к методу quit() виджета QApplication. Это завершает приложение.
exitAction.triggered.connect(app.quit)
• Метод menuBar() создаёт строку меню. Мы создаём меню «File» и добавляем в него действие выхода из
приложения.
menubar = self.menuBar()
fileMenu = menubar.addMenu('File')
fileMenu.addAction(exitAction)

66.

Панель инструментов
• Все команды из меню, которые мы можем использовать в приложении. Панели инструментов
предоставляют быстрый доступ к большинству часто используемых команд.
• мы создадим простую панель инструментов. Она имеет один инструмент, действие выхода, которое
завершает приложение, будучи инициированным.
• В аналогичном примере как с созданием меню выше, мы создаём объект действия. Объект имеет метку,
иконку и горячую клавишу. Метод quit() из QtGui.QMainWindow присоединяется к инициирующему сигналу.
exitAction = QAction(QIcon('exit24.png'), 'Exit', self)
exitAction.setShortcut('Ctrl+Q')
exitAction.triggered.connect(app.quit)

67.

Панель инструментов
• Здесь мы создаём панель инструментов и подключаем объект действия к ней.
self.toolbar = self.addToolBar('Exit')
self.toolbar.addAction(exitAction)

68.

Задания
• Сделайте приложение, с меню из 5 основных пунктов, в одном из пунктов сделайте выпадающее меню в
3 пункта

69.

Задания

70.

Задания
• Создайте простую игру с помощью QMainWindow. Добавьте меню "Игры" с опциями "Новая игра"
и "Выход", а также меню "Справка" с опциями "Инструкции" и "О программе". Везде добавьте
горячие клавиши

71.

Задания

72.

Управление макетом

73.

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

74.

Абсолютное позиционирование
• Программист указывает позицию и размер каждого виджета в пикселях. При использовании абсолютного
позиционирования, мы должны понимать следующие ограничения:
Размер и позиция виджета не меняются, если мы меняем размер окна
Приложения могут выглядеть по-разному на разных платформах
Изменение шрифтов в нашем приложении может испортить макет
Если мы решаем изменить наш макет, мы должны полностью переделать его, что утомительно и время-
затратно.
Мы используем метод move(), чтобы разместить наши виджеты. В этом случае ими являются метки. Мы
размещаем их путём предоставления координат x и y. Начало координатной системы – левый верхний
угол. Значения x возрастают слева направо. Значения y растут сверху вниз.

75.

Блочный макет
• Управление макетом с классами макета является более гибким и практичным. Это предпочтительный
путь размещения виджетов в окне. QHBoxLayout и QVBoxLayout – это основные классы макета, которые
выстраивают виджеты горизонтально или вертикально.
• QHBoxLayout выстраивает виджеты горизонтально, один за другим. Он полезен для создания
горизонтальных макетов, где виджеты располагаются рядом друг с другом. Например, вы можете
использовать QHBoxLayout для создания панели инструментов с несколькими кнопками.
hbox_layout = QtWidgets.QHBoxLayout()
hbox_layout.addWidget(QtWidgets.QPushButton("Button 1"))
hbox_layout.addWidget(QtWidgets.QPushButton("Button 2"))
hbox_layout.addWidget(QtWidgets.QPushButton("Button 3"))
• Этот код создает горизонтальный макет, содержащий три кнопки.

76.

Блочный макет
• QVBoxLayout, с другой стороны, выстраивает виджеты вертикально, один над другим. Он полезен для
создания вертикальных макетов, где виджеты располагаются друг над другом. Например, вы можете
использовать QVBoxLayout для создания диалогового окна с несколькими полями.
vbox_layout = QtWidgets.QVBoxLayout()
vbox_layout.addWidget(QtWidgets.QLineEdit())
vbox_layout.addWidget(QtWidgets.QTextEdit())
vbox_layout.addWidget(QtWidgets.QCheckBox())
• Этот код создает вертикальный макет, содержащий редактирование строки, редактирование текста и
флажок.

77.

Блочный макет
• Вы также можете использовать метод addLayout() для вложения макетов внутрь других макетов. Это
позволяет создавать более сложные макеты.
• Вы также можете использовать метод addStretch() для добавления растягиваемого пространства между
виджетами в макете. Метод принимает один аргумент - целочисленное значение, которое задает
коэффициент растяжения пространства.
• Вы также можете использовать метод setSpacing() для управления пространством между виджетами в
макете.
• Вы также можете использовать метод setContentsMargins() для управления полями вокруг макета.
• Можно также использовать метод setAlignment() для выравнивания виджетов внутри макета коробки.
• Вы также можете использовать метод setStretchFactor() для управления коэффициентом растяжения для
виджета в макете. Этот метод принимает два аргумента - виджет и коэффициент растяжения.

78.

Блочный макет
• Представьте, что мы хотим разместить две кнопки в правом нижнем углу. Чтобы создать такой макет, мы
будем использовать один горизонтальный и один вертикальный блок. Чтобы создать необходимое
свободное пространство, мы добавим показатель растяжения.
def initUI(self):
okButton = QPushButton("OK")
cancelButton = QPushButton("Cancel")
hbox = QHBoxLayout()
hbox.addStretch(1)
hbox.addWidget(okButton)
hbox.addWidget(cancelButton)
vbox = QVBoxLayout()
vbox.addStretch(1)
vbox.addLayout(hbox)
self.setLayout(vbox)
self.setGeometry(300, 300, 300, 150)
self.setWindowTitle('Buttons')
self.show()

79.

Блочный макет
• Пример размещает две кнопки в нижнем правом углу окна. Они остаются там, когда мы
изменяем размер окна приложения. Мы можем использовать и HBoxLayout, и QVBoxLayout.
okButton = QPushButton("OK")
cancelButton = QPushButton("Cancel")
#Здесь мы создаём две кнопки.
hbox = QHBoxLayout()
hbox.addStretch(1)
hbox.addWidget(okButton)
hbox.addWidget(cancelButton)

80.

Блочный макет
• Чтобы создать необходимый макет, мы поставим горизонтальный макет в вертикальный.
Показатель растяжения в вертикальном блоке прижмёт горизонтальный блок с кнопками к
нижней части окна.
self.setLayout(vbox)

81.

Сеточный макет
• QGridLayout - это менеджер компоновки, который используется для расположения виджетов в
сетке. Каждая ячейка в сетке может содержать один виджет. Виджеты размещаются в сетке,
начиная с левого верхнего угла и двигаясь слева направо и сверху вниз.
• Вы можете использовать метод addWidget(), чтобы добавить виджет в определенную ячейку
сетки. Метод принимает четыре аргумента: добавляемый виджет, строку, столбец и
выравнивание. Например:
grid_layout = QtWidgets.QGridLayout()
grid_layout.addWidget(QtWidgets.QLabel("Label 1"), 0, 0)
grid_layout.addWidget(QtWidgets.QLabel("Label 2"), 0, 1)
grid_layout.addWidget(QtWidgets.QLabel("Label 3"), 1, 0)
grid_layout.addWidget(QtWidgets.QLabel("Label 4"), 1, 1)
• Этот код создает макет сетки, содержащий четыре метки, расположенные в сетке 2x2.

82.

Сеточный макет
• Метод addWidget() используется для добавления виджета в определенную ячейку QGridLayout.
Метод принимает четыре аргумента: виджет для добавления, строка, столбец и
выравнивание.
• Первый аргумент - это виджет, который вы хотите добавить в макет сетки. Это может быть
виджет любого типа, например, кнопка, метка или текстовый редактор.
• Второй и третий аргументы - это строка и столбец ячейки, в которой будет размещен виджет.
Эти значения индексируются по нулям, поэтому левая верхняя ячейка находится на (0,0), а
правая нижняя - на (rowCount-1, columnCount-1).
• Четвертый аргумент - это выравнивание виджета внутри ячейки. Это может быть любая
комбинация следующих флагов выравнивания:
• Qt.AlignLeft
• Qt.AlignRight
• Qt.AlignTop
• Qt.AlignBottom
• Qt.AlignCenter

83.

Сеточный макет
• Например, следующий код создает макет сетки с двумя кнопками и помещает одну кнопку в
левую верхнюю ячейку (0,0), а другую - в правую нижнюю (1,1) с выравниванием AlignCenter
grid_layout = QGridLayout()
grid_layout.addWidget(QPushButton("Button 1"), 0, 0, Qt.AlignmentFlag.AlignCenter)
grid_layout.addWidget(QPushButton("Button 2"), 1, 1, Qt.AlignmentFlag.AlignCenter)

84.

Сеточный макет
• Есть метод addLayout() для вложения макетов в макет сетки. Это позволяет создавать более
сложные макеты.
• Есть метод addItem() для добавления пустых ячеек в макет сетки. Метод принимает один
аргумент, объект QSpacerItem, который можно использовать для управления размером пустой
ячейки.
• Есть методы setRowStretch() и setColumnStretch() для управления размером строк и столбцов в
макете сетки. Эти методы принимают один аргумент - целочисленное значение, которое
задает коэффициент растяжения для строки или столбца.
• Есть методы setRowMinimumHeight() и setColumnMinimumWidth() для управления минимальным
размером строк и столбцов в макете сетки.
• Есть методы setHorizontalSpacing() и setVerticalSpacing() для управления пространством между
виджетами в макете сетки.
• Есть метод setSpacing() для установки пространства между виджетами и пространства между
виджетами и краем макета.
• Есть метод setContentsMargins() для управления полями вокруг макета.

85.

Сеточный макет
• Самый универсальный класс макета – это сеточный макет. Этот макет делит пространство на
строки и столбцы. Чтобы создать сеточный макет, мы используем класс QGridLayout.
grid = QGridLayout()
self.setLayout(grid)
names = ['Cls', 'Bck', '', 'Close', '7', '8', '9', '/', '4', '5', '6', '*', '1', '2', '3', '-', '0',
'.', '=',
'+']
positions = [(i, j) for i in range(5) for j in range(4)]
for position, name in zip(positions, names):
if name == '':
continue
button = QPushButton(name)
grid.addWidget(button, *position)
self.move(300, 150)
self.setWindowTitle('Calculator')

86.

Сеточный макет
• В нашем примере, мы создаём сетку из кнопок. Чтобы заполнить один промежуток, мы
добавляем один виджет QLabel.
• Создаётся экземпляр QGridLayout, он назначается как макет окна приложения.
grid = QGridLayout()
self.setLayout(grid)

87.

Сеточный макет
• Это метки, используемые в дальнейшем для кнопок.
• Мы создаём список позиций для сетки.
names = ['Cls', 'Bck', '', 'Close', '7', '8', '9', '/', '4', '5', '6', '*', '1', '2', '3', '-', '0', '.', '=', '+’]
positions = [(i,j) for i in range(5) for j in range(4)]

88.

Сеточный макет
• Используя метод addWidget, создаются и добавляются кнопки к макету.
for position, name in zip(positions, names):
if name == '':
continue
button = QPushButton(name)
grid.addWidget(button, *position)

89.

Сеточный макет
• Виджеты могут охватывать несколько столбцов и строк в сетке

90.

Сеточный макет
• Мы создаём окно, в котором мы имеем три метки, две строки правки и один виджет
редактирования текста. Макет сделан с помощью QGridLayout.
title = QLabel('Title')
author = QLabel('Author')
review = QLabel('Review')
titleEdit = QLineEdit()
authorEdit = QLineEdit()
reviewEdit = QTextEdit()
• Мы создаём сеточный макет и устанавливаем промежуток между виджетами.
grid = QGridLayout()
grid.setSpacing(10)

91.

Сеточный макет
• Если мы добавляем виджет к сетке, мы можем обеспечить объединение строк и столбцов
виджета. В нашем примере, мы делаем так, что виджет reviewEdit объединяет 5 строк.
grid.addWidget(reviewEdit, 3, 1, 5, 1)
• Мы создаём сеточный макет и устанавливаем промежуток между виджетами.
grid = QGridLayout()
grid.setSpacing(10)

92.

Задания
• Повторите форму с помощью блочного и сеточного макета

93.

Задания
• Повторите форму с помощью блочного и сеточного макета

94.

Задания
• Повторите форму с помощью блочного и сеточного макета, в ней используется 3 метки (QLabel)
и 3 однострочных текстовых поля (QLineEdit)

95.

Задания
• Повторите форму с помощью блочного и сеточного макета

96.

Qt Designer

97.

Qt Designer
• Qt Designer — кроссплатформенная свободная среда для разработки графических интерфейсов (GUI) для
программ, использующих библиотеку Qt.
• Qt Designer позволяет создавать графические интерфейсы пользователя при помощи ряда инструментов.
Существует панель инструментов «Панель виджетов», в которой доступны для использования элементы
интерфейса — виджеты, такие как, например, «выпадающий список» ComboBox, «поле ввода» LineEdit,
«кнопка» PushButton и многие другие. Каждый виджет имеет свой набор свойств, определяемый
соответствующим ему классом библиотеки Qt.

98.

Установка
• Возможно придется установить другую версию Python… (3.9.1
например)
• pip install PyQt6==6.0.2
• pip install pyqt6-tools==6.0.2.3.2

99.

Ищем дизайнера
После установки он будет доступен по такому пути:
C:\Users\*Ваш_юзер*\AppData\Local\Programs\Python\Python39\Lib\sitepackages\qt6_applications\Qt\bin
И ищем там designer.exe

100.

Смотрим интерфейс

101.

Сохраняем UI файл
После составления дизайна сохраняем его в отдельный файл с
расширением .ui

102.

Превращаем дизайн в код
Конечно, можно использовать .ui-файлы напрямую из Python-кода,
однако есть и другой путь, который может показаться легче. Можно
конвертировать код .ui-файла в Python-файл, который мы потом
сможем импортировать и использовать. Для этого мы используем
команду pyuic5 из терминала/командной строки.
Чтобы конвертировать .ui-файл в Python-файл с названием design.py,
используйте следующую команду:
pyuic6 -x .\cool-app.ui -o cool-app.py

103.

Пишем код
Теперь у нас есть файл cool-app.py с нужной частью дизайна нашего
приложения и мы начинаем работу над созданием его логики.

104.

Задания
• Создайте простой графический интерфейс с QMainWindow, QLabel и QPushButton. На метке
должно отображаться сообщение, а кнопка должна изменять сообщение при нажатии.

105.

Задания
• Создайте графический интерфейс с QMainWindow, двумя QLineEdits и QLabel.
Изменения в двух строках следует использовать для ввода двух чисел, а в метке должна
отображаться их сумма.

106.

Задания
• Повторите форму с помощью блочного и сеточного макета

107.

Задания
• Повторите форму с помощью блочного и сеточного макета

108.

Задания
• Повторите форму с помощью блочного и сеточного макета, в ней используется 3 метки (QLabel)
и 3 однострочных текстовых поля (QLineEdit)

109.

Задания
• Повторите форму с помощью блочного и сеточного макета
English     Русский Rules