GUI QT6
- QT6 + оглавление
- QT6Core
- QT6 настройка окна
- QT6 desiner
- QT6 QLabel, LCD
- QT6 Buttons
- QT6 QLineEdit
- QT6 CheckBox, SpinBox, ComboBox
- QT6 QSlider, QListWidget
- QT6 QTable, QMessageBox, Dialogs
- Пример: notepad
- QT6: База данных
QT6 + оглавление
Платная лицензия Похоже надо углубиться в лицензирование opensource.
Страницы компонентов
| Label | Push button | Radio button |
| Line edit | Check box | SpinBox |
| QLCD | ComboBox | Slider |
| ListWidget | Table | Calendar |
| ColorDialog | FontDialog | MessageBox |
| Dialogs (save) |
Установка:
pip install pyqt6
pip install pyqt6-tools
Минимальное приложение:
from PyQt6.QtWidgets import QApplication, QWidget
import sys
app = QApplication(sys.argv)
window = QWidget()
window.show()
sys.exit(app.exec())
Архитектура QT прячется под стандартную, но это не так. QT основывается на цикле событий, внутри реализованы используемые системные процедуры (таймер, ...), и приходится использовать соответствующие QT-модули, а не системные модули. Поэтому в составе QT много модулей.
| Модуль | Назначение |
| QtWidgets |
Основной и шаблонные виджеты (окно, метка, ...) |
| QtGui |
Классы для интеграции с оконной системой, обработки событий, 2D-графики, базовых изображений, шрифтов, иконок и текста.
QIcon класс работы с иконками |
| QtCore |
Системные модули. |
Типы окон
QMainWindow Главное окно приложения и связанные с ним классы для управления главным окном.
from PyQt6.QtWidgets import QApplication, QMainWindow
import sys
app = QApplication(sys.argv)
window = QMainWindow()
window.statusBar().showMessage("Welcome to pyqt6 coding")
window.show()
sys.exit(app.exec())
QMainWindow имеет свой собственный макет, содержащий QToolBars, QDockWidgets, QMenuBar и QStatusBar.
QDialog Базовый класс окна верхнего уровня, используемое для краткосрочных задач и краткого общения с пользователем.
QDialogs может быть модальным или немодальным.
QWidget Базовый класс всех объектов пользовательского интерфейса, получает мышь, клавиатуру и другие события
из оконной системы и отображает свое изображение на экране.
Объектно-ориентированный подход настройки окна
Создаем класс-потомок например от QWidget или QMainWindow, настраиваем свойства и
from PyQt6.QtWidgets import QApplication, QWidget
from PyQt6.QtGui import QIcon
import sys
class Window(QWidget):
def __init__(self):
super().__init__()
self.setGeometry(200,200, 700, 400)
self.setWindowTitle("Python GUI Development")
self.setWindowIcon(QIcon('pyqt6lessons\images\python.png'))
self.setStyleSheet('background-color:green')
self.setWindowOpacity(0.5)
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec())
Управление событиями
Основной элемент всех приложений в Qt — класс QApplication. Каждому приложению нужен только один объект QApplication, который содержит цикл событий приложения. Это основной цикл, управляющий всем взаимодействием пользователя с графическим интерфейсом.
При каждом взаимодействии с приложением генерируется событие, которое помещается в очередь событий. В цикле событий очередь проверяется на каждой итерации: если найдено ожидающее событие, оно вместе с управлением передаётся определённому обработчику этого события. Последний обрабатывает его, затем возвращает управление в цикл событий и ждёт новых событий. Для каждого приложения выполняется только один цикл событий.
Класс QApplication содержит цикл событий Qt (нужен один экземпляр QApplication). Приложение ждёт в цикле событий новое событие, которое будет сгенерировано при выполнении действия. Всегда выполняется только один цикл событий.
Сигналы — уведомления, отправляемые виджетами, когда что-то происходит. Это может быть нажатие кнопки, изменение текста в поле ввода, изменение текста в окне, ... Многие сигналы инициируются в ответ на действия пользователя, но не только: в сигналах могут отправляться данные с дополнительным контекстом произошедшего.
Слоты — приёмники сигналов. Слотом можно сделать любую функцию (или метод), просто подключив к нему сигнал. Принимающая функция получает данные, отправляемые ей в сигнале. У многих виджетов Qt есть встроенные слоты, эти виджеты можно подключать друг к другу напрямую.
class Window(QWidget):
def __init__(self):
super().__init__()
self.setGeometry(200,200, 700, 400)
self.setWindowTitle("Python GUI Development")
self.create_button()
def create_button(self):
btn = QPushButton("Click", self)
btn.clicked.connect(self.the_button_was_clicked)
def the_button_was_clicked(self):
print("Clicked")
Соединение сигнала и слота происходит в функции btn.clicked.connect(self.the_button_was_clicked) Таблицы событий:
Мышь:
| Тип | Описание |
|---|---|
MouseButtonPress |
Нажата кнопка мыши |
MouseButtonRelease |
Отпущена кнопка мыши |
MouseButtonDblClick |
Двойной клик |
MouseMove |
Движение мыши |
Wheel |
Колёсико мыши |
Enter |
Курсор вошёл в виджет |
Leave |
Курсор покинул виджет |
HoverEnter |
Hover вошёл |
HoverMove |
Hover движение |
HoverLeave |
Hover вышел |
Клавиатура:
| Тип | Описание |
|---|---|
KeyPress |
Нажата клавиша |
KeyRelease |
Отпущена клавиша |
Shortcut |
Сработал shortcut |
ShortcutOverride |
Попытка перехвата shortcut |
InputMethod |
IME ввод |
InputMethodQuery |
Запрос IME |
Фокус и активация
| Тип | Описание |
|---|---|
FocusIn |
Получен фокус |
FocusOut |
Потерян фокус |
ActivationChange |
Изменение активности окна |
Окна и виджеты
| Тип | Описание |
|---|---|
Show |
Виджет показан |
Hide |
Виджет скрыт |
Close |
Закрытие |
Resize |
Изменение размера |
Move |
Перемещение |
Paint |
Перерисовка |
LayoutRequest |
Запрос layout |
UpdateRequest |
Запрос обновления |
Polish |
Финальная инициализация |
PolishRequest |
Запрос polish |
ParentChange |
Изменился родитель |
ParentAboutToChange |
Родитель изменится |
WindowStateChange |
Изменение состояния окна |
WindowActivate |
Окно активировано |
WindowDeactivate |
Окно деактивировано |
WindowTitleChange |
Заголовок окна |
WindowIconChange |
Иконка окна |
WindowBlocked |
Окно заблокировано |
WindowUnblocked |
Окно разблокировано |
Геометрия и экран
| Тип | Описание |
|---|---|
ScreenChangeInternal |
Изменился экран |
ScreenChangeInternal |
DPI/Screen изменился |
OrientationChange |
Смена ориентации |
DevicePixelRatioChange |
Изменение DPR |
Drag & Drop
| Тип | Описание |
|---|---|
DragEnter |
Drag вошёл |
DragMove |
Drag перемещение |
DragLeave |
Drag покинул |
Drop |
Drop |
Буфер обмена
| Тип | Описание |
|---|---|
Clipboard |
Изменился буфер обмена |
Таймеры
| Тип | Описание |
|---|---|
Timer |
Сработал таймер |
ZeroTimerEvent |
Таймер с нулевой задержкой |
Touch / Tablet / Gesture
| Тип | Описание |
|---|---|
TouchBegin |
Touch начало |
TouchUpdate |
Touch обновление |
TouchEnd |
Touch конец |
TabletPress |
Перо нажато |
TabletMove |
Перо движение |
TabletRelease |
Перо отпущено |
Gesture |
Жест |
GestureOverride |
Перехват жеста |
Состояние
| Тип | Описание |
|---|---|
EnabledChange |
Изменение enabled |
FontChange |
Изменение шрифта |
StyleChange |
Изменение стиля |
PaletteChange |
Изменение палитры |
LanguageChange |
Смена языка |
LocaleChange |
Смена локали |
ThemeChange |
Смена темы |
ApplicationStateChange |
Состояние приложения |
Продвинутые опции
| Тип | Описание |
|---|---|
DynamicPropertyChange |
Изменение свойства |
ChildAdded |
Добавлен ребёнок |
ChildRemoved |
Удалён ребёнок |
ChildPolished |
Ребёнок отполирован |
MetaCall |
Вызов meta-object |
ThreadChange |
Смена потока |
DeferredDelete |
Отложенное удаление |
Quit |
Завершение приложения |
PlatformSurface |
Изменение поверхности |
PlatformPanel |
Platform panel |
User |
Начало пользовательских событий |
Пользовательские события
| Тип | Описание |
|---|---|
User |
Базовый пользовательский event |
MaxUser |
Максимальный ID |
event = QEvent(QEvent.Type.User)
QCoreApplication.postEvent(obj, event)
Поиск событий:
def event(self, event):
print(event.type())
return super().event(event)
#или
widget.installEventFilter(self)
def eventFilter(self, obj, event):
print(obj, event.type())
return False
QT6Core
QTime класс управления / работы со временем.
time = QTime.currentTime()
text = time.toString('hh:mm')
QTimer класс тайминга. Настраивается при инициализации класса.
class Window(QWidget):
def __init__(self):
super().__init__()
self.setGeometry(200,200, 700, 400)
self.setWindowTitle("Python GUI Development")
self.timer = QTimer()
self.timer.timeout.connect(self.update_lcd)
self.timer.start(1000)
self.create_button()
QT6 настройка окна
Компоновщики (Layouts).
Нужны для автоматического упорядочивания и изменения размеров виджетов при изменении размера окна. Без Layouts виджеты имеют фиксированные позиции и размеры. Импортируются все типы компоновщиков через
from PyQt6.QtWidgets import QHBoxLayout
Типы Layouts в Qt Designer
| Vertical Layout (Вертикальный компоновщик) | Располагает виджеты сверху вниз в столбик.
|
| Horizontal Layout (Горизонтальный компоновщик) | Располагает виджеты слева направо в строку.
|
| Grid Layout (Сеточный компоновщик) | Располагает виджеты в таблице (строках и столбцах).
|
| Form Layout (Формовый компоновщик) | Идеален для форм (метка + поле ввода). Располагает виджеты в две колонки: labels слева, поля справа.
|
class Window(QWidget):
def __init__(self):
super().__init__()
self.setGeometry(200,200, 700, 400)
self.mainlayout = QVBoxLayout()
bt1 = QPushButton("one")
bt2 = QPushButton("two")
bt3 = QPushButton("three")
bt4 = QPushButton("four")
self.mainlayout.addWidget(bt1)
self.mainlayout.addWidget(bt2)
self.mainlayout.addWidget(bt3)
self.mainlayout.addWidget(bt4)
self.setLayout(self.mainlayout)
Базовый подход:
- Перетащите виджеты на форму
- Выделите несколько виджетов (зажав Ctrl)
- Нажмите правой кнопкой → "Lay out" → Выберите нужный тип
- Или используйте панель инструментов сверху (кнопки с иконками Layouts)
Вложенные Layouts:
Main Vertical Layout
├── Horizontal Layout (для кнопок)
│ ├── Кнопка "Открыть"
│ ├── Кнопка "Сохранить"
│ └── Кнопка "Выход"
└── Text Edit (занимает оставшееся пространство)
Еще класс, просто для примера. Соотношение 1:2
class Window(QWidget):
'''
Вложенные Layout
'''
def __init__(self):
super().__init__()
self.setGeometry(200,200, 700, 400)
self.setWindowTitle("Python GUI Development")
self.mainlayout = QVBoxLayout()
lbl1 = QLabel("one label")
lbl2 = QLabel("two label")
bt1 = QPushButton("one")
bt2 = QPushButton("two")
self.innerlayout1 = QHBoxLayout()
self.innerlayout1.addWidget(lbl1, stretch=1)
self.innerlayout1.addWidget(bt1,stretch=2)
self.mainlayout.addLayout(self.innerlayout1)
self.innerlayout2 = QHBoxLayout()
self.innerlayout2.addWidget(lbl2, stretch=1)
self.innerlayout2.addWidget(bt2,stretch=2)
self.mainlayout.addLayout(self.innerlayout2)
self.setLayout(self.mainlayout)
Растяжения (Stretch):
В коде: layout.addStretch()
В Designer: есть специальный виджет "Horizontal Spacer" / "Vertical Spacer"
Выравнивание: В Property Editor настраивается
- layoutStretch — пропорции растяжения
- alignment — выравнивание содержимого
- spacing — расстояние между виджетами, пустое место
self.mainlayout.addSpacing(100)
- margin — отступ от краев
Пожелания при использовании Layouts
- Всегда используйте центральный Layout для главного окна
- Не смешивайте абсолютное позиционирование и Layouts
- Тестируйте ресайз окна
- Используйте Spacers для гибких промежутков
- Настройте stretch factors для управления пропорциями
Stretch Factors
Stretch factor — числовое значение, определяющее пропорцию, в которой виджеты делят доступное пространство при растяжении окна.
Базовые принципы:
- По умолчанию stretch factor = 0
- Виджет сохраняет свой минимальный размер
- Не растягивается при увеличении окна
- Чем больше значение, тем больше пространства получает виджет
- Важны относительные пропорции
Настройка при создании
Способ 1: Панель свойств (Property Editor)
- Выберите Layout в иерархии объектов
- Найдите свойство layoutStretch или layoutRowStretch / layoutColumnStretch
- Введите значения через запятую
В данном примере первая кнопка не будет менять размеры, вторая будет занимать 20% от оставшегося свободного места, третья 80%.
Способ 2:Через свойства виджетов внутри Layout
У каждого виджета есть свойство sizePolicy → horizontalStretch / verticalStretch
Способ 3: Через код
# при добавлении нового виджета
self.mainlayout.addWidget(bt1, stretch=1)
self.mainlayout.addWidget(bt2, stretch=3)
self.mainlayout.addWidget(bt3, stretch=0)
self.mainlayout.addWidget(bt4, stretch=5)
Настройка после создания
Способ 1: Использовать setStretch(index, stretch)
# Предположим, у вас уже есть Layout с виджетами
self.mainlayout.addWidget(bt1, stretch=1)
self.mainlayout.addWidget(bt2, stretch=3)
self.mainlayout.addWidget(bt3, stretch=0)
self.mainlayout.addWidget(bt4, stretch=5)
# Позже меняем stretch для bt4 (индекс 3, так как индексы начинаются с 0)
self.mainlayout.setStretch(3, 2) # Меняем с 5 на 2
Способ 2: Получить индекс виджета динамически
# Находим индекс виджета bt4 в Layout
index = self.mainlayout.indexOf(bt4)
if index != -1: # -1 означает "не найден"
self.mainlayout.setStretch(index, 2)
Способ 3: Пересоздать Layout (более кардинальный)
# Удаляем все виджеты из Layout
while self.mainlayout.count():
item = self.mainlayout.takeAt(0)
if item.widget():
item.widget().hide()
# Добавляем заново с новыми stretch factors
self.mainlayout.addWidget(bt1, stretch=1)
self.mainlayout.addWidget(bt2, stretch=3)
self.mainlayout.addWidget(bt3, stretch=0)
self.mainlayout.addWidget(bt4, stretch=2) # Новое значение!
Способ 4: Изменить через setSizePolicy виджета.
# Получаем текущую политику размеров
policy = bt4.sizePolicy()
# Устанавливаем горизонтальный/вертикальный stretch
policy.setHorizontalStretch(2) # Для Horizontal Layout
policy.setVerticalStretch(2) # Для Vertical Layout
bt4.setSizePolicy(policy)
bt4.update() # Обновляем виджет
Важно: Этот метод влияет на поведение виджета во всех Layout, где он находится!
Способ 5: Временное отключение обновления для избежания мерцания при изменении:
# Блокируем обновление
self.setUpdatesEnabled(False)
# Меняем stretch
index = self.mainlayout.indexOf(bt4)
self.mainlayout.setStretch(index, 2)
# Включаем обновление и форсируем перерасчет
self.setUpdatesEnabled(True)
self.mainlayout.invalidate() # Помечаем Layout как невалидный
self.mainlayout.activate() # Принудительно пересчитываем
Особенности работы:
- Изменения применяются немедленно — Layout пересчитается при следующем обновлении интерфейса
- Индексы начинаются с 0 и соответствуют порядку добавления
- Spacer'ы тоже имеют индексы — учитывайте это при поиске
- setStretch() работает только для QBoxLayout (QVBoxLayout, QHBoxLayout)
- Для QGridLayout используйте setRowStretch() и setColumnStretch()
- Для QFormLayout сложнее — лучше удалить и добавить заново
Проверка текущих значений:
# Получить текущий stretch factor
current_stretch = self.mainlayout.stretch(3) # Для индекса 3
print(f"Текущий stretch: {current_stretch}")
# Получить список всех stretch factors
for i in range(self.mainlayout.count()):
widget = self.mainlayout.itemAt(i).widget()
stretch = self.mainlayout.stretch(i)
if widget:
print(f"Индекс {i}: {widget.text()} - stretch={stretch}")
Класс окна
Для управления классом окна, класс создается, затем настраиваются нужные свойства
from PyQt6.QtWidgets import QApplication, QWidget
from PyQt6.QtGui import QIcon
import sys
class Window(QWidget):
def __init__(self):
super().__init__()
self.setGeometry(200,200, 700, 400)
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec())
Свойства:
self.setWindowIcon(QIcon('pyqt6lessons\images\python.png'))
self.setStyleSheet('background-color:green')
self.setWindowOpacity(0.5)
| Свойство | Применение |
| Размеры окна |
self.setGeometry(x,y, height, width) self.setGeometry(200,200, 700, 400) |
| Заголовок окна | self.setWindowTitle("Python GUI Development") |
QT6 desiner
Устанавливается при установке pyqt6-tools
У меня вызвался обычной командой
(myenv) D:\projects\calclulator_long>pyside6-designer.exe
Типы создаваемых окон:
- 3 типа диалоговых окон,
- Основное окно
- 10 виджетов.
Различаются родительским классом и наличием дополнительных виджетов (кнопки, ...)
Предпросмотр результата
Блок меню Form - Preview... очень занимательный.
QT использует стили операционных систем, поэтому вид будет отличаться на разных ОС.
Слои (Layouts)
Настраивается отдельно тип для всей формы и для группы элементов.
Настройка для группы элементов: выделяются виджеты, ПКМ - Lay Out - Нужный тип.
Для всей формы: ПКМ на пустом месте формы - Lay Out - Нужный тип.
Использование .ui файла
Использование в скрипте
Два варианта: преобразование в py файл и загрузка в py скрипт ui-файла во время выполнения.
Преобразование в python файл:
(myenv) D:\projects\calclulator_long>pyuic6 -x testui.ui -o testuicreated.py
После этого запуск *,py файла откроет пользовательский интерфейс. При изменении *.ui файла необходимо обновить файл исходного кода и связанных процедур.
Загрузка ui файла во время выполнения
from PyQt6.QtWidgets import QApplication, QWidget
import sys
from PyQt6 import uic
class UI(QWidget):
def __init__(self):
super().__init__()
uic.loadUi("WindowUI.ui", self)
app = QApplication(sys.argv)
window = UI()
window.show()
app.exec()
Доступ к виджетам внутри .ui файла
Для дальнейшего доступа к виджетам из py скрипта необходимо знать тип виджета и имя объекта. Например, есть виджет типа QLineEdit, имя объекта lineEdit_price.
Создадим свойство объекта через FindChild
class UI(QWidget):
def __init__(self):
super().__init__()
uic.loadUi("double_spin.ui", self)
self.linePrice = self.findChild(QLineEdit, "lineEdit_price")
Дальше с этим свойством работать также как с созданным объектом. Пример:
lass UI(QWidget):
def __init__(self):
super().__init__()
uic.loadUi("double_spin.ui", self)
self.linePrice = self.findChild(QLineEdit, "lineEdit_price")
self.doublespin = self.findChild(QDoubleSpinBox, "doubleSpinBox")
self.doublespin.valueChanged.connect(self.spin_selected)
self.lineresult = self.findChild(QLineEdit, "lineEdit_total")
def spin_selected(self):
if self.linePrice.text() != 0:
price = int(self.linePrice.text())
totalPrice = self.doublespin.value() * price
self.lineresult.setText(str(totalPrice))
Соединение действий виджетов
Функционал урезан. Нажать кнопку Edit signals/slots
При наведении мыши виджет становится красным. Если нажать виджет, с которого сигнал будет исходить и, удерживая мышь, переместить указатель на виджет, на который будет влиять сигнал, появится стрелка и элемент выбора сигналов/слотов.
Нужно установить флажок внизу. Выбирается сигнал, слот и все работает даже на превью.
QT6 QLabel, LCD
QLabel
Класс QLabel используется для отображения сообщений и изображений,
- Импорт QLabel
- Создание объекта класса QLabel
- Применение методов класса к переменной
from PyQt6.QtWidgets import QApplication, QWidget, QLabel
import sys
class Window(QWidget):
def __init__(self):
super().__init__()
self.setGeometry(200,200, 700, 400)
self.setWindowTitle("Python GUI Development")
label = QLabel("", self)
label.setText('first text in label')
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec())
Для создания метки с изображением текст не передается
label = QLabel(self)
Таблица методов:
| Метод | Назначение |
| setText() | Устанавливается новый текст метки |
| setNum() | добавляет целое или двойное значение |
| clear() | удаляет текст |
| setMovie() |
установки изображения gif movie = QMovie('images/sky.gif') |
| setFont() | Изменения шрифта, setFont() ожидает класс QFont, (потомок QtGui) label.setFont(QFont("Sanserif", 15)) |
| label.setStyleSheet() |
Изменение цвета шрифта label.setStyleSheet('color:red') |
| Добавление изображения |
|
| setPixamp() | pixmap = QPixmap('images/python.png') label.setPixmap(pixmap) |
| QImage, QBitmap QPicture |
QLCDNumber
Класс для отображения 7-сегментного дисплея, отображает 5 (пять) 8- 10- 16- ричных элементов.
class Window(QWidget):
def __init__(self):
super().__init__()
self.setGeometry(200,200, 700, 400)
self.setWindowTitle("Python GUI Development")
self.timer = QTimer()
self.timer.timeout.connect(self.update_lcd)
self.timer.start(1000)
self.create_button()
def create_button(self):
vbox = QVBoxLayout()
self.lcd = QLCDNumber()
self.lcd.setStyleSheet('background:red')
vbox.addWidget(self.lcd)
time = QTime.currentTime()
text = time.toString('hh:mm')
self.lcd.display(text)
self.setLayout(vbox)
def update_lcd(self):
time = QTime.currentTime()
text = time.toString('hh:mm')
self.lcd.display(text)
QT6 Buttons
Командная кнопка является наиболее часто используемым виджетом в любом графическом интерфейсе пользователя. Нажатие (click) кнопки является командой компьютеру выполнить какое-либо действие. Типичными кнопками являются "ОК", "Применить", "Отмена", "Закрыть"., Да, Нет и Справка.
Командная кнопка имеет прямоугольную форму и обычно отображает текстовую метку, описывающую ее действие. Можно указать комбинацию клавиш, указав перед нужным символом амперсанд в тексте.
чтобы отобразить кнопку в приложении, вам необходимо создать экземпляр класса QPushButton.
from PyQt6.QtWidgets import QApplication, QWidget, QPushButton
import sys
class Window(QWidget):
def __init__(self):
super().__init__()
self.setGeometry(200,200, 700, 400)
self.setWindowTitle("Python GUI Development")
self.create_button()
def create_button(self):
btn = QPushButton("Click", self)
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec())
Методы класса:
| Метод | Описание |
| setText() | Изменение текста |
| setIcon() |
Добавление иконки на кнопку btn.setIcon(QIcon("images/python.png")) |
|
Изменение размера иконки
|
|
| setGeometry() | Настройка положения кнопки, |
| setMenu() |
Всплывающее меню над кнопкой. Сначала создать объект QMenu, класс QMenu связан с модулем QtWidgets, класс QMenu предоставляет виджет меню для использования в строках меню, контекстных меню и других всплывающих меню.
|
| setFont() |
Настройка шрифта btn.setFont(QFont("Times", 14, QFont.Weight.ExtraBold)) |
| setCheckable() |
Вид кнопки при нажатии меняется. Выделяется и снимается выделение. |
Кнопка, которую можно включить (установить флажок) или выключить (снять флажок). Переключатели обычно предоставляют
пользователю возможность выбора "из многих". В группе переключателей одновременно может быть установлен только один переключатель, если пользователь выбирает другую кнопку, ранее выбранная кнопка отключается. Существуют различные методы, которые вы можете использовать, например, у нас есть IsChecked(), и он возвращает логическое значение true, если кнопка находится в выбранном состоянии, или у нас есть метод setIcon(), с помощью которого мы можем добавить значок для радиокнопки, а также setText(), который задает текст выбранной кнопки. Также существуют различные сигналы, которые вы можете использовать, например, у нас есть переключаемый сигнал, который используется всякий раз, когда переключатель меняет свое состояние с установленного на снятое и наоборот.
from PyQt6.QtWidgets import QApplication, QWidget, QHBoxLayout, QRadioButton, QLabel
from PyQt6.QtWidgets import QVBoxLayout
import sys
class Window(QWidget):
def __init__(self):
super().__init__()
self.setGeometry(200,200, 700, 400)
self.setWindowTitle("Python GUI Development")
self.create_button()
def create_button(self):
hbox = QHBoxLayout()
self.label = QLabel("", self)
vbox = QVBoxLayout()
vbox.addWidget(self.label)
vbox.addLayout(hbox)
rad1 = QRadioButton("Python")
rad1.toggled.connect(self.radio_selected)
hbox.addWidget(rad1)
rad2 = QRadioButton("Java")
rad2.toggled.connect(self.radio_selected)
hbox.addWidget(rad2)
rad3 = QRadioButton("JavaScript")
rad3.toggled.connect(self.radio_selected)
hbox.addWidget(rad3)
self.setLayout(vbox)
def radio_selected(self):
radio_btn = self.sender()
if radio_btn.isChecked():
self.label.setText(f'Selected: {radio_btn.text()}')
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec())
Методы класса:
| Метод | Описание |
| isChecked() | Возвращает True если кнопка выбрана |
| setChecked() | Переводит кнопку в выбранное состояние |
| setIcon() | Устанавливает иконку кнопки |
| setText() | Текст |
QT6 QLineEdit
Виджет позволяет вводить и редактировать одну строку обычного текста с помощью полезного набора функций редактирования, включая отмену и повтор, вырезание и вставку, а также перетаскивание.
Методы:
| Метод | Назначение |
| setEchoMode() |
Режим эхо. Варианты:
|
| setFont() | Настройка шрифта |
| maxLength() | Максимальная длина текста |
| setText() | Устанавливает текст |
| text() | Получает текст |
| clear() | Очищает строку ввода |
| setReadOnly() | Установка режима только для чтения |
| setEnabled() | Доступность компонента пользователю |
| setFocus() | Установить фокус |
| setPlaceholderText() | Текст когда поле пустое |
QT6 CheckBox, SpinBox, ComboBox
QCheckbox
Это кнопка выбора, которую можно включить (установить флажок) или выключить (снять флажок). Флажки обычно используются для обозначения функций в приложении, которые можно включать или отключать, не затрагивая другие. При изменении состояния флажка выдается сигнал StateChanged(). Метод IsChecked() используется для запроса, установлен ли флажок.
Методы:
| Метод | Описание |
| isChecked() | |
| setIcon() | |
| setText() | |
| setChecked() |
Сигналы:
stateChanged
QSpinbox
QSpinBox предназначен для обработки целых чисел и дискретных наборов значений, позволяет выбирать значение, нажимая кнопки вверх / вниз или нажимая клавиши вверх / вниз на клавиатуре, чтобы увеличить / уменьшить отображаемое в данный момент значение. Также возможно ввести значение вручную.
Методы:
| Метод | Описание |
| value() | текущее выбранное целое значение |
| text() | отображения текста в окне прокрутки |
|
setMinimum() |
|
| setMaximum() | |
| setPrefix() | текстовый префикс, добавляемый перед значением, возвращаемым полем прокрутки. |
| setSuffix() | текст суффикса, добавляемый к значению, возвращаемому блоком spin. |
Сигналы:
valueChanged()
editingFinished() выдается при потере фокуса на spinbox. Предполагаю, актуально для приложений с web backend при передаче финальных данных.
from PyQt6.QtWidgets import QApplication, QWidget, QLabel, QHBoxLayout, QLineEdit
from PyQt6.QtWidgets import QSpinBox
import sys
class Window(QWidget):
def __init__(self):
super().__init__()
self.setGeometry(200,200, 700, 400)
self.setWindowTitle("Python GUI Development")
self.create_button()
def create_button(self):
hbox = QHBoxLayout()
label = QLabel("Laptop price: ")
self.lineedit = QLineEdit()
self.spinbox = QSpinBox()
self.spinbox.valueChanged.connect(self.spin_selected)
self.total_result = QLineEdit()
hbox.addWidget(label)
hbox.addWidget(self.lineedit)
hbox.addWidget(self.spinbox)
hbox.addWidget(self.total_result)
self.setLayout(hbox)
def spin_selected(self):
if self.lineedit.text() != 0:
price = int(self.lineedit.text())
totalPrice = self.spinbox.value() * price
self.total_result.setText(str(totalPrice))
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec())
QComboBox
Виджет выбора, отображающий текущий элемент. Также отображает список выбираемых элементов. Может быть редактируемым.
Также есть специализированный ComboBox: для выбора шрифтов (fontComboBox).
Методы:
| Метод | Описание |
| setItemText() | Устанавливает или изменяет текст элемента в поле со списком. |
| removeItem() | Удаляет определенный элемент из поля со списком. |
| clear() | Удаляет все элементы из поля со списком. |
| currentText() | Возвращает текст текущего элемента, то есть элемента, который выбран в данный момент. |
| setCurrentIndex() | Устанавливает текущий индекс поля со списком, то есть задает желаемый элемент в поле со списком в качестве выбранного в данный момент элемента. |
| count() | Возвращает количество элементов в поле со списком. |
| setEditable() | Сделайте поле со списком доступным для редактирования, то есть пользователь можно редактировать элементы в поле со списком. |
| addItem() | Добавляет указанное содержимое в поле со списком. |
| itemText() | Возвращает текст в указанное расположение индекса в поле со списком. |
| currentIndex() | Возвращает индексное местоположение текущего выбранного элемента в поле со списком. Если поле со списком пусто или в поле со списком в данный момент не выбран ни один элемент, метод вернет значение -1 в качестве индекса. |
Сигналы
currentIndexChanged() выбор нового элемента
editTextChanged() изменение текста в редактируемом комбобоксе
from PyQt6.QtWidgets import QApplication, QWidget, QComboBox, QLabel, QHBoxLayout, QVBoxLayout
import sys
class Window(QWidget):
def __init__(self):
super().__init__()
self.setGeometry(200,200, 700, 400)
self.setWindowTitle("Python GUI Development")
self.create_button()
def create_button(self):
hbox = QHBoxLayout()
label = QLabel('Select type: ')
self.combo = QComboBox()
self.combo.addItem('')
self.combo.addItem('Current account')
self.combo.addItem('Deposite account')
self.combo.addItem('Saving account')
self.combo.currentTextChanged.connect(self.updresult)
hbox.addWidget(label)
hbox.addWidget(self.combo)
vbox = QVBoxLayout()
vbox.addLayout(hbox)
self.label_result = QLabel('')
vbox.addWidget(self.label_result)
self.setLayout(vbox)
def updresult(self):
self.label_result.setText('Your type: ' + self.combo.currentText())
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec())
QT6 QSlider, QListWidget
QSlider
Ползунок - виджет управления ограниченным значением. Позволяет перемещать ручку ползунка и преобразовывать положение ручки в целое значение в допустимом диапазоне.
Слайдер бывает горизонтальным и вертикальным
self.slider.setOrientation(Qt.Orientation.Horizontal)
Настройка положения галочки ползунка
self.slider.setTickPosition(QSlider.TickPosition.TicksAbove)
Интервал шага
self.slider.setTickInterval(5)
Границы диапазона
self.slider.setMinimum(0)
self.slider.setMaximum(100)
Методы
| Метод | Назначение |
| minimum() | возвращает минимальное значение ползунка |
| maximum() | возвращает максимальное значение ползунка |
| setValue() | используется для установки значения ползунка |
Сигналы
| Сигнал | Назначение |
| valueChanged() | подается при перемещении ручки ползунка |
| sliderPressed() | подается, когда пользователь начинает перетаскивать ручку ползунка. |
| sliderMoved() | подается, когда пользователь перемещает ручку ползунка. |
| sliderReleased() | подается, когда пользователь отпускает ручку ползунка |
QListWidget
QListWidget - представление списка, аналогичное QListView, но с классическим интерфейсом на основе элементов для добавления и удаления элементов. QListWidget использует внутреннюю модель для управления удалением элементов. QListWidget использует внутреннюю модель для управления каждым QListWidgetItem в списке.
Методы
| Метод | Назначение |
| insertItem() | вставляет новый элемент в виджет списка в указанном месте. |
| insertItems() | вставляет несколько элементов из предоставленного списка, начиная с указанного места |
| count() | возвращает количество элементов в списке. |
| takeItem() | удаляет и возвращает элементы из указанной строки |
| CurrentItem() | возвращает текущий элемент в списке |
| addItem() | добавляет элемент с указанным текстом в конец |
| currentRow() | возвращает номер строки выбранного элемента. Если ни один элемент не выбран, возвращает -1 |
Сигналы
| Сигнал | Назначение |
| clicked() | подается при щелчке по элементу в виджете списка |
| currentRowChanged() | подается при изменении строки текущего элемента списка |
| currentTextChanged() | подается при каждом изменении текста в текущем элементе списка |
| currentItemChanged() | подается при изменении фокуса текущего элемента списка |
QT6 QTable, QMessageBox, Dialogs
QTable
Отображение таблиц. Элементы в QTableWidget предоставляются с помощью QTableWidgetItem.
Методы:
| Метод | Назначение |
| setRowCount() | определения количества строк |
| setColumnCount() | определения количества столбцов |
| rowCount() | возвращает количество строк |
| columnCount() | возвращает количество столбцов |
from PyQt6.QtWidgets import QApplication, QWidget, QTableWidget, QTableWidgetItem, QVBoxLayout
import sys
class Window(QWidget):
def __init__(self):
super().__init__()
self.setGeometry(200,200, 700, 400)
self.setWindowTitle("Python GUI Development")
self.create_button()
def create_button(self):
vbox = QVBoxLayout()
curtable = QTableWidget()
curtable.setRowCount(3)
curtable.setColumnCount(3)
curtable.setItem(0, 0, QTableWidgetItem('Заголовок столбца 1'))
curtable.setItem(0, 1, QTableWidgetItem('Заголовок столбца 2'))
curtable.setItem(0, 2, QTableWidgetItem('Заголовок столбца 3'))
vbox.addWidget(curtable)
self.setLayout(vbox)
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec())
QMessageBox
QMessageBox - модальный диалог информирования пользователя и получения ответа. В окне сообщения отображается текст, есть необязательный подробный текст в случае необходимости. Также может отображаться значок и стандартные кнопки для принятия ответа пользователя. Существуют различные типы диалогов (about messagebox, information messagebox, warning messagebox, multichoice messagebox).
from PyQt6.QtWidgets import QApplication, QDialog, QPushButton
from PyQt6.QtWidgets import QMessageBox
from PyQt6 import uic
import sys
class Window(QDialog):
def __init__(self):
super().__init__()
self.setGeometry(200,200, 700, 400)
self.setWindowTitle("Python GUI Development")
uic.loadUi("messagedemo.ui", self)
self.loadguiobjects()
def loadguiobjects(self):
self.butt_warn = self.findChild(QPushButton, "pushButton_warn")
self.butt_warn.clicked.connect(self.show_warn)
self.butt_info = self.findChild(QPushButton, "pushButton_info")
self.butt_info.clicked.connect(self.show_info)
self.butt_abt = self.findChild(QPushButton, "pushButton_abt")
self.butt_abt.clicked.connect(self.show_about)
def show_warn(self):
QMessageBox.warning(self, 'Warning', 'This is a warning message')
def show_info(self):
#кастомный messagebox + стандартные кнопки
msg_box = QMessageBox(self)
msg_box.setWindowTitle('Information')
msg_box.setText('This is a information message')
msg_box.setIcon(QMessageBox.Icon.Information)
# Добавляем кнопки
ok_button = msg_box.addButton('OK', QMessageBox.ButtonRole.AcceptRole)
cancel_button = msg_box.addButton('Отменить задание', QMessageBox.ButtonRole.RejectRole)
# Показываем сообщение и ждем нажатия кнопки
msg_box.exec()
# Проверяем какая кнопка была нажата
if msg_box.clickedButton() == cancel_button:
print("Действие отменено")
elif msg_box.clickedButton() == ok_button:
print("OK нажата")
def show_about(self):
# другой способ с разными кнопкам
msg_box = QMessageBox(
QMessageBox.Icon.NoIcon,
'About',
'This is a about message',
QMessageBox.StandardButton.Ok | QMessageBox.StandardButton.Cancel
)
# Изменяем текст стандартных кнопок
msg_box.button(QMessageBox.StandardButton.Ok).setText('Продолжить')
msg_box.button(QMessageBox.StandardButton.Cancel).setText('Отменить задание')
result = msg_box.exec()
if result == QMessageBox.StandardButton.Ok:
print("Продолжаем выполнение")
else:
print("Задание отменено")
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec())
SaveFile
Сама кнопка меню в сформированном из QtDesiner, класс Ui_MainWindow
from PyQt6.QtWidgets import QMainWindow, QApplication, QFileDialog, QMessageBox
import sys
from notepadapp import Ui_MainWindow
class NotePadWindow(QMainWindow, Ui_MainWindow):
def __init__(self):
super().__init__()
self.setupUi(self)
self.show()
self.actionSave.triggered.connect(self.save_file)
def save_file(self):
filename = QFileDialog.getSaveFileName(self, 'Save file')
if filename[0]:
f = open(filename[0], 'w')
with f:
text = self.textEdit.toPlainText()
f.write(text)
QMessageBox.about(self, 'Save file', 'File saved successfully!')
app = QApplication(sys.argv)
Note = NotePadWindow()
sys.exit(app.exec())
Пример: notepad
Начальная информация
Внешний вид приложения:
Элементы интерфейса: меню, быстрые кнопки и многострочное поле ввода. Элементы меню:
Установленные модули:
pip install pyqt6
Параметры интерфейса:
Окно - MainWindow
from PyQt6.QtWidgets import QMainWindow, QApplication, QFileDialog, QMessageBox
from PyQt6.QtPrintSupport import QPrinter, QPrintDialog, QPrintPreviewDialog
from PyQt6.QtCore import QFileInfo
from PyQt6.QtGui import QFont
import sys
from notepadapp import Ui_MainWindow
class NotePadWindow(QMainWindow, Ui_MainWindow):
def __init__(self):
super().__init__()
self.setupUi(self)
self.show()
self.actionSave.triggered.connect(self.file_save)
self.actionNew.triggered.connect(self.file_new)
self.actionOpen.triggered.connect(self.file_open)
self.actionPrint.triggered.connect(self.file_print)
self.actionPrint_preview.triggered.connect(self.preview_dialog)
self.actionExport_PDF.triggered.connect(self.exporting_pdf)
self.actionQuit.triggered.connect(self.exit_app)
self.actionUndo.triggered.connect(self.textEdit.undo)
self.actionRedo.triggered.connect(self.textEdit.redo)
self.actionCut.triggered.connect(self.textEdit.cut)
self.actionCopy.triggered.connect(self.textEdit.copy)
self.actionPaste.triggered.connect(self.textEdit.paste)
self.actionBold.triggered.connect(self.text_bold)
def maybe_save(self) -> bool:
if not self.textEdit.document().isModified():
return True
ret = QMessageBox.warning(self, "Application",
"The document changed \n Save working?",
QMessageBox.StandardButton.Save |
QMessageBox.StandardButton.Discard |
QMessageBox.StandardButton.Cancel)
if ret == QMessageBox.StandardButton.Save:
self.file_save()
return True
elif ret == QMessageBox.StandardButton.Cancel:
return False
return True
def file_new(self):
if self.maybe_save():
self.textEdit.clear()
def file_save(self):
filename = QFileDialog.getSaveFileName(self, 'Save file')
if filename[0]:
f = open(filename[0], 'w')
with f:
text = self.textEdit.toPlainText()
f.write(text)
QMessageBox.about(self, 'Save file', 'File saved successfully!')
def file_open(self):
self.maybe_save()
filename = QFileDialog.getOpenFileName(self, 'Open file')
if filename[0]:
f = open(filename[0], 'r')
with f:
data = f.read()
self.textEdit.setText(data)
def file_print(self):
printer = QPrinter(QPrinter.PrinterMode.HighResolution)
dialog = QPrintDialog(printer)
if dialog.exec() == QPrintDialog.DialogCode.Accepted:
self.textEdit.print(printer)
def print_preview(self, printer):
self.textEdit.print(printer)
def preview_dialog(self):
printer = QPrinter(QPrinter.PrinterMode.HighResolution)
preview_dialog = QPrintPreviewDialog(printer, self)
preview_dialog.paintRequested.connect(self.print_preview)
preview_dialog.exec()
def exporting_pdf(self):
#fn, _ = QFileDialog.getSaveFileName(self, 'Export PDF', "PDF Files (.pdf) ;; AllFiles()")
fn, _ = QFileDialog.getSaveFileName(self, 'Export PDF','',"PDF Files (.pdf) ;; All Files (*)")
if QFileInfo(fn).suffix() == "":
fn += '.pdf'
printer = QPrinter(QPrinter.PrinterMode.HighResolution)
printer.setOutputFormat(QPrinter.OutputFormat.PdfFormat)
printer.setOutputFileName(fn)
self.textEdit.document().print(printer)
def exit_app(self):
self.close()
def text_bold(self):
font = QFont()
font.setBold(True)
self.textEdit.setFont(font)
app = QApplication(sys.argv)
Note = NotePadWindow()
sys.exit(app.exec())
Это неполный код, операции однотипные.
QT6: База данных
Пример для работы с Mysql
pip install mysql-connector-python
Пример кода для подключения к базе и создания БД:
from PyQt6 import QtCore, QtGui, QtWidgets
import mysql.connector as mc
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(456, 300)
self.verticalLayout = QtWidgets.QVBoxLayout(Form)
self.verticalLayout.setObjectName("verticalLayout")
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.label_dbname = QtWidgets.QLabel(parent=Form)
font = QtGui.QFont()
font.setPointSize(14)
self.label_dbname.setFont(font)
self.label_dbname.setObjectName("label_dbname")
self.horizontalLayout.addWidget(self.label_dbname)
self.lineEdit_dbname = QtWidgets.QLineEdit(parent=Form)
font = QtGui.QFont()
font.setPointSize(14)
self.lineEdit_dbname.setFont(font)
self.lineEdit_dbname.setText("")
self.lineEdit_dbname.setObjectName("lineEdit_dbname")
self.horizontalLayout.addWidget(self.lineEdit_dbname)
self.verticalLayout.addLayout(self.horizontalLayout)
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Expanding)
self.verticalLayout.addItem(spacerItem)
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.pushButton_dbcreate = QtWidgets.QPushButton(parent=Form)
self.pushButton_dbcreate.setObjectName("pushButton_dbcreate")
self.pushButton_dbcreate.clicked.connect(self.create_db)
self.horizontalLayout_2.addWidget(self.pushButton_dbcreate)
self.pushButton_dbconn = QtWidgets.QPushButton(parent=Form)
self.pushButton_dbconn.setObjectName("pushButton_dbconn")
self.pushButton_dbconn.clicked.connect(self.check_connect)
self.horizontalLayout_2.addWidget(self.pushButton_dbconn)
self.verticalLayout.addLayout(self.horizontalLayout_2)
self.label_result = QtWidgets.QLabel(parent=Form)
font = QtGui.QFont()
font.setFamily("PMingLiU-ExtB")
font.setPointSize(14)
self.label_result.setFont(font)
self.label_result.setText("")
self.label_result.setObjectName("label_result")
self.verticalLayout.addWidget(self.label_result)
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def create_db(self):
try:
mydb = mc.connect(
host="192.168.1.193",
user="root",
password="rootpassword"
)
cursor = mydb.cursor()
dbname = self.lineEdit_dbname.text()
cursor.execute("CREATE DATABASE {} ".format(dbname))
self.label_result.setText('Database {} created!'.format(dbname))
except mc.Error as e:
self.label_result.setText(str(e))
def check_connect(self):
try:
mydb = mc.connect(
host="192.168.1.193",
user="root",
password="rootpassword",
database="pyqtdb"
)
self.label_result.setText("Connected!")
except mc.Error as e:
self.label_result.setText(str(e))
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "Form"))
self.label_dbname.setText(_translate("Form", "Database name:"))
self.pushButton_dbcreate.setText(_translate("Form", "Create Database"))
self.pushButton_dbconn.setText(_translate("Form", "Database connection"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
Form = QtWidgets.QWidget()
ui = Ui_Form()
ui.setupUi(Form)
Form.show()
sys.exit(app.exec())