Topic 2 of 6

Course materials are currently available in Russian only.

Окно, виджеты и раскладки

PySide6 — официальная библиотека Qt для Python. Qt — один из самых известных наборов для программ с окнами: на нём сделаны VirtualBox, Telegram Desktop, Autodesk Maya, KDE. В отличие от Tkinter, PySide6 выглядит современно и умеет почти всё: таблицы, графику, мультимедиа, веб-страницы внутри окна.

В курсе вы соберёте приложение для заметок: окно, кнопки, список заметок, редактор и сохранение в файл.

В курсе ставится пакет PySide6-Essentials — основные модули Qt (окна, виджеты, графика), около 80 МБ. Полный PySide6 весит в несколько раз больше: в нём ещё веб-браузер, 3D и мультимедиа.

Минимальная программа

import sys
from PySide6.QtWidgets import QApplication, QWidget, QLabel, QPushButton, QVBoxLayout


class Window(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Привет")
        self.label = QLabel("Нажми кнопку")
        button = QPushButton("Нажми")
        button.clicked.connect(self.on_click)
        layout = QVBoxLayout(self)
        layout.addWidget(self.label)
        layout.addWidget(button)

    def on_click(self):
        self.label.setText("Нажато!")


app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec())
  • QApplication — сама программа, создаётся один раз и до окон;
  • окно — класс-наследник QWidget (или QMainWindow — с меню и строкой состояния);
  • window.show() показывает окно, app.exec() запускает цикл событий.

Виджеты

Виджет Что это Главное
QLabel надпись setText, text()
QPushButton кнопка сигнал clicked, setEnabled
QLineEdit поле ввода text(), setText, сигнал textChanged, setPlaceholderText
QTextEdit многострочный текст toPlainText(), setPlainText
QCheckBox флажок isChecked(), сигнал toggled
QSpinBox число со стрелками value(), setRange

Раскладки

Виджеты не расставляют по координатам — их кладут в раскладки, которые сами подстраиваются под размер окна:

from PySide6.QtWidgets import QHBoxLayout, QGridLayout

column = QVBoxLayout(self)            # сверху вниз; self — окно-владелец
row = QHBoxLayout()                   # слева направо
row.addWidget(QPushButton("OK"))
row.addWidget(QPushButton("Отмена"))
column.addLayout(row)                 # раскладка внутри раскладки

grid = QGridLayout()
grid.addWidget(QPushButton("7"), 0, 0)          # строка 0, столбец 0
grid.addWidget(QPushButton("="), 3, 2, 1, 2)    # занять 1 строку и 2 столбца

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

Когда что-то происходит (нажали кнопку, изменили текст), виджет испускает сигнал. К сигналу подключают функцию — слот:

button.clicked.connect(self.on_click)        # без скобок!
edit.textChanged.connect(self.on_text)       # слот получит новый текст

К одному сигналу можно подключить несколько слотов — и одну функцию случайно подключить дважды: тогда она будет вызываться дважды.

Как проверяются задачи

Окно создаётся под if __name__ == "__main__":. Проверка создаёт ваше окно без экрана (Qt умеет работать «вслепую») и нажимает кнопки программно — button.click(), как будто это сделал человек. «Запустить у себя» открывает настоящее окно.

Итог

  • QApplication один раз, окно — наследник QWidget, show(), app.exec();
  • виджеты QLabel, QPushButton, QLineEdit;
  • раскладки QVBoxLayout, QHBoxLayout, QGridLayout;
  • сигнал → слот: clicked.connect(функция).