Туториал - создание блокнота в QT Designer

QT - популярная кросс-языковая и кроссплатформенная библиотека для создания графических пользовательских интерфейсов для персональных компьютеров и т.п. Она имеет поддержку тем и стилей, взаимодействия с клавиатуры и все обычные горячие клавиши, а главное, широкое распространение и большое количество инструментов, чтобы облегчить работу с ней.

Сегодня я расскажу вам о QT Designer, графическом инструменте для создания интерфейсов на QT.

Видео Ссылка на заголовок

Подготовка Ссылка на заголовок

Установка QT Designer Ссылка на заголовок

Windows Ссылка на заголовок

Загрузите и установите исполняемый файл QT, найденный в официальном веб-сайте или установите пакеты вроде pyqt5 или pyqt6 для Python при помощи pip.

Затем вам нужно проверить путь установки, найти файл designer.exe и запустить его.

Linux Ссылка на заголовок

Установите пакет qt development tools, который имеет различные имена в зависимости от вашего дистрибутива.

sudo apt install qttools5-dev-tools # QT5, Ubuntu/Mint
sudo apt install qttools6-dev-tools # QT6, Ubuntu/Mint

sudo dnf install qt5-qttools-libs-designer # QT5, Fedora
sudo dnf install qt5-qttools-libs-designer # QT6, Fedora

sudo pacman -S qt5-tools #QT5, Arch
sudo pacman -S qt6-tools #QT6, Arch

nix-shell -p libsForQt5.qt5.qttools # QT5, Nix
nix-shell -p qt6.qttools # QT6, Nix

После этого запустите designer в командной строке, открыв Qt Designer, или напишите .desktop файл для быстрого запуска из интерфейса.

Интерфейс QT Designer Ссылка на заголовок

Это находится главное окно QT дизайнера. Для простоты я выделила важные регионы на скриншоте.

Скриншот оконного интерфейса с выделенными частями: 1 - пустое фальшивое окно, 2 - список объектов в этом окне, 3 - таблица со свойствами, 4 - комбинированная часть интерфейса, в которой находится редактор сигналов/слотов, выбранный на картинке, 4 - список всех возможных виджетов, 6 - кнопки-иконки, 7 - строка меню.

  1. Главная Рабочая Зона
  2. Инспектор Объектов
  3. Редактор Свойств
  4. Редактор Сигналов (и две других вкладки)
  5. Список Виджетов
  6. Лента с кнопками
  7. Лента меню

Создание интерфейса Ссылка на заголовок

Итак, мы создадим простой интерфейс для текстового редактора (“блокнота”). Для этого нам нужно три вида виджетов:

Различные кнопки представляют собой виджет PushButton, фактическое пространство для редактирования реализовано с помощью TextEdit wigdet, а строка поиска - LineEdit.

Интерфейс перетаскиванием Ссылка на заголовок

Одна из вещей, которая совершенно неправильно объяснена во многих похожих туториалах, это то, как они просят вас вручную перетащить виджеты из окна виджетов (5) в ваш интерфейс (1) и расположить их так, как вы хотите. Если мы попробуем сделать это, то все получится, но…

Уменьшая окно мы обрезаем Интерфейс. А увеличивая, мы добавляем много лишнего пустого места.

Как видите, это не очень хорошо масштабируется…

Использование макетов Ссылка на заголовок

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

Самые основные из них - горизонтальный и вертикальный макеты:

Вертикальная раскладка (QVBoxLayout) располагает виджеты один за другим по вертикали, а горизонтальная (QHBoxLayout) - по горизонтали.

Мы будем использовать сетчатый макет:

Сетчатый макет (QGridLayout) позволяет добавлять виджеты как по горизонтали, так и по вертикали.

Поэтому мы размещаем наши виджеты на сетке так, как нам нужно…

Макет-сетка с нашими виджетами, но текстовый редактор занимает только одну колонку

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

Макет сетки с нашими виджетами и с текстовым редактором, занимающим всю ширину.

Также вы можете добавить виджет горизонтальный разделитель для разделения кнопок и строки поиска.

Добавленный горизонтальный разделитель позволяет легче определить, что это разные части интерфейса.

Затем мы нажимаем правую кнопку вне макета и выбираем Lay out в контекстном меню, выбирая любой из макетов, упомянутых выше, чтобы преобразовать само окно в макет.

В контекстном меню отображается множество опций, выбрана опция Lay out, а внутри нее - опция 'Lay Out in a grid', которую также можно вызвать, нажав Ctrl + 5. Сетчатый макет теперь занимает все окно!

Изменение свойств виджетов Ссылка на заголовок

Изменить текст на кнопке довольно просто: дважды щелкните на ней левой кнопкой мыши и введите свой текст.

Но нам нужно гораздо больше изменений, поэтому мы выберем виджеты либо напрямую выделяя их, либо с помощью инспектора объектов (2), затем перейдем к свойствам объекта (3), чтобы отредактировать нужные нам.

Имя ID Описание
Object Name objectName Идентификатор объекта, используемый в коде, поэтому убедитесь, что его легко понять
Text text Текст на кнопках и других объектах. Для редактирования текста и редактирования строк он будет помещать уже существующий “настоящий” текст, а не текст-заполнитель, который вам обычно нужен.
Placeholder Text placeholderText Серые подсказки внутри виджетов редактирования строки и текста
Tooltip toolTip Текст, который отображается при наведении курсора на кнопку, напишите здесь более подробное описание

Результат будет выглядеть следующим образом:

Окно блокнота, кнопки Новый файл, Открыть и Сохранить, строка поиска имеет текст-заполнитель 'Поиск...' с подсказкой для кнопки Новый файл, говорящей 'Создать новый файл, стерев текущий текст, если он не сохранен'.

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

Специальное имя acessibleName Имя объекта, которое программа чтения с экрана читает для пользователей с ослабленным зрением
Специальное описание acessibleDescription Что-то вроде подсказки для пользователей программ для чтения с экрана

Tab order Ссылка на заголовок

Правильный порядок виджетов, с другой стороны, позволяет использовать кнопку Tab для фокусировки на следующем (или предыдущем, при использовании Shift+Tab) интерактивном виджете, используя только клавиатуру, что также полезно для пользователей программ чтения с экрана и других людей, которым необходимо перемещаться по вашему приложению с клавиатуры.

Выделена кнопка Изменить Tab Order.

Выберите режим Редактировать Tab Order в Ленте кнопок (6) и проверьте, пронумерованы ли кнопки в порядке слева направо, сверху вниз, если нет, нажмите на все из них в этом порядке.

Окно с виджетами, пронумерованными от 1 до 5.

Для этой же цели можно использовать список порядка вкладок.

Щелчок правой кнопкой мыши по виджету и выбор пункта контекстного меню “Список упорядоченных вкладок”

Окно списка вкладок с упорядоченным списком виджетов

Настройка действий Ссылка на заголовок

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

  1. Дважды нажмите на Type here в пустой строке меню вашего окна и введите название категории.
  2. Нажмите еще раз и выберите Type here в выпадающем меню, на этот раз введя название действия. Здесь же можно добавить разделители групп действий.
  3. Выберите новое действие и отредактируйте запись shortcut в редакторе свойств, добавив горячие клавиши.

Процесс выполнения вышеописанных шагов.

Для нашего простого редактора я рекомендую следующий список горячих клавиш и действий:

Категория > Имя Шорткат
Файл > Новый Ctrl+N
Файл > Открыть… Ctrl+O
Файл > Сохранить Ctrl+S
Файл > Сохранить как… Ctrl+Shift+S
Файл > Выйти Ctrl+Q
Редактирование > Поиск Ctrl+F

Сигналы Ссылка на заголовок

Наконец, мы должны добавить сигналы. Сигналы позволяют нам соединять различные окна и/или действия, чтобы изменение состояния одного из них влияло на другое. В нашем случае мы хотим, чтобы наши кнопки были связаны с соответствующими действиями, а действие Поиск фокусировало нашу панель поиска.

Мы могли бы использовать кнопку из панели кнопок (6) для входа в режим редактирования сигналов, но она не позволяет подключать действия, поэтому мы будем использовать Редактор сигналов (4) для добавления нового сигнала и выбора:

  1. Кнопка по её objectName в качестве Sender
  2. clicked() в качестве Сигнала
  3. Действие по objectName в качестве получателя
  4. trigger() как Slot

Таблица редактора сигналов на примере кнопок newFileButton и actionNew_file

В свою очередь, для действия Поиск нам нужно использовать triggered() и setFocus()

Тот же пример, но с добавлением searchBar и action_search.

Проделайте это для всех кнопок, и мы практически закончили работу с QT дизайнером, осталось только сохранить проект как .ui файл и поместить его в папку проекта.

Подключение интерфейса к коду PyQT5 Ссылка на заголовок

После того как мы закончим со всем этим, нам все равно нужно будет внедрить этот интерфейс в наше приложение. В качестве примера мы будем использовать PyQT5, библиотеку языка Python для QT.

Загрузка интерфейса из кода Ссылка на заголовок

Чтобы загрузить интерфейс, у нас есть два разных способа. Один из них - преобразовать ui-файл, который мы можем сохранить из QT Designer, в python-код, используя инструмент командной строки uic или сгенерировав его из самого QT Designer.

pyuic5 interface_filename.ui > interface_filename.py
from PyQt5.QtWidgets import QMainWindow, QApplication
from interface_filename import Ui_MainWindow

class MainWindow(QMainWindow):

    def __init__(self):
        super().__init__() # инициализация QMainWindow
        
        # Загрузка и применение интерфейса из py файла
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

app = QApplication(sys.argv)
w = MainWindow()
w.show()
app.exec_()

Другой способ - использовать uic в качестве библиотеки и загружать UI-файл напрямую, конвертируя его во время выполнения. Второй способ добавляет немного нагрузки на компьютер в приложение и требует поставки ui файла вместе с ним, но позволяет быстро протестировать изменения в .ui файле, просто перезапустив код.

from PyQt5.QtWidgets import QMainWindow, QApplication
from PyQt5 import uic

class MainWindow(QMainWindow):

    def __init__(self):
        super().__init__() # инициализация QMainWindow
        
        # Загрузка и применение интерфейса из ui файла
        uic.loadUi("interface_filename.ui",self)

app = QApplication(sys.argv)
w = MainWindow()
w.show()
app.exec_()

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

  • В первом методе объекты называются как self.ui.objectName, поскольку мы импортировали их как объект с именем ui, в то время как во втором методе мы используем просто self.objectName.
  • Если вы используете второй метод, он странно игнорирует настройки отступов центрального виджета, из-за чего у него нет пространства между кнопками и краями окна, поэтому нам нужно, чтобы у нашего макета сетки, добавленного вручную, был отступ, что мы сделаем используя редактор свойств (3) (Вы также можете установить свойство margin на 0 в центральном виджете, чтобы не было несоответствия между способами)

Таблица свойств с layoutLeftMargin и аналогичными свойствами для других сторон, установленными на 10.

Подключение к функциям Ссылка на заголовок

После этого нам нужно добавить несколько функций, которые заставят наш интерфейс работать. Здесь я не буду подробно рассказывать о том, как работают эти функции, так как это в основном видео по qt designer, поэтому мы сосредоточимся на том, как подключить их к нашим виджетам.

QT Designer сделал за нас часть работы, позволив нам просто вызывать виджеты из кода по их именам (в случае Python, self.objectName для метода uic как библиотеки, или self.ui.objectName, если мы использовали первый метод), поэтому мы добавим код, который свяжет сигналы действия triggered с функциями в __init__ нашего объекта MainWindow.

self.ui.actionNew_file.triggered.connect(self.create_new_file)
# ИЛИ
self.actionNew_file.triggered.connect(self.create_new_file)

Для кнопок мы бы использовали clicked вместо triggered, но мы уже связали их с сигналами, так что в этом нет необходимости.

Исключением является поле поиска, мы используем returnPressed для запуска функции поиска.

self.ui.searchBar.returnPressed.connect(self.search_text)
# ИЛИ
self.searchBar.returnPressed.connect(self.search_text)
Информация
QT Designer избавил нас от необходимости вручную назначать горячих клавиш для действий и писать в два раза больше кода для подключения действий.

Conclusion Ссылка на заголовок

Полные файлы проекта вы можете найти здесь - https://codeberg.org/system-maid/cute-writer.

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