GUI BUILDER ДЛЯ TKINTER.
Технология tkinter мне чертовски нравится - вам предлагают создавать gui компактно, переносимо и лаконично. Как я отмечал в предыдущих заметках ( Некорявый tkinter - Часть 1 и Некорявый tkinter - Часть 2 ), старомодный и неказистый интерфейс в последние годы был модернизирован с помощью новейших библиотек. Учитывая, что python (с которым я начал работать в далёком 2000 г., и тогда же опубликовал забавную заметку про работу с данными на python, в ту пору python выглядел как реактивный самолёт после паровоза-perl), ныне оказался на пике технологий, возрастающий интерес к этой библиотеке можно легко объяснить.
В этой заметке речь пойдёт о графических интерфейсах и средстве визуального проектирования графических интерфейсов для tkinter.
Напомню, что tkinter - это компактная библиотека для создания мультиплатформеногого gui в python. И, хотя, этот набор виджетов довольно ограничен, но он давно присутствует во всех версиях python , и, в качестве инструмента для создания несложного графического интерфейса, вполне подходит и довольно часто используется вместе с современными библиотеками (pandas, matplotlib и пр.).
Большим недостатком библиотеки, по-моему мнению, являлось отсутствие визуальных средств создания форм. В других графических тулкитах (gtk, QT или wxwidgets) подобные средства существует давно и такой способ визуальной разработки графических интерфейсов для программистов привычен, понятен и удобен. В случае с tkinter подобные попытки неоднократно предпринимались. Не могу сказать, что они были удачными. Но вот кажется что-то похожее на желаемое уже появилось.
Программа явно создана создана под влиянием glade, который хорошо знают пользователи Gnome/gtk. Так что теперь можно создавать экранные формы визуально, с помощью программы-дизайнера, сохранять созданные формы во внешний файл, который можно впоследствии использовать для автоматического создания форм и дописывать обработчики событий. И хотя программа довольно сыровата и не все функции реализованы, но лучшего решения я пока не видел, задачу быстрого создания форм программа вполне решает.
Способ работы с программой очень нагляден. Совершенно естественным способом, ссылки, на нарисованные виджеты, можно получить внутри вашей программы, после чего вы можете модифицировать свойства и реализовать все желаемые обработчики событий, и это не потребует сложных усилий. Собственно нарисовать интерфейс в визуальной манере, сохранить его виде xml ресурса, затем загрузить и получить работающий прототип графического интерфейса за несколько минут - это как раз тот самый способ, который сильно упрощает жизнь и экономит время. Удивительную лаконичность и компактность кода tkinter и pygubu я бы назвал рекордными. Код получается заметно короче чем в gtk, QT или wxwidgets...
Установка
Самый простой способ для установки пакетов это pip.
python -m pip install pygubu
python -m pip install pygubu-designer
Традиционный HELLO WORLD
Попробуем создать простейшее приложение.
Поскольку мы пользуемся pygubu - оберткой вокруг tkinter, то мы должны позаботиться об аккуратной инициализации программы. В качестве видежета верхнего уровня рекомендуется использовать tk.Toplevel. В него вкладываем виджет-контейнер ttk.Frame, далее можно добавлять любые виджеты.
Создадим следующие элементы интерфейса:
* ttk.Frame
* ttk.Label
* ttk.Label
* ttk.Button
Для меток зададим текстовые надписи, скомпонуем объекты, укажем расстояния между элементами и для ttk.Button укажем property command=on_ok_clicked. Компоновка объектов немного утомительна и требует понимания принципов компоновщика tkinter. Но программа позволяет поиграться с компоновкой объектов визуально и очень сильно ускоряет процесс понимания принципов работы разных алгоритмов компоновки.
Думаю вы согласитесь, визуально всё-таки намного проще задать разумные интервалы между объектами. По умолчанию tkinter создаёт слишком плотное расположение элементов, поэтому очень часто программы имеют довольно "скомканный" интерфейс.
Сохраняем созданную форму hello.ui
Про генерацию кода
Программа предполагает три режима генерации кода :
Application/Code Script/Custom Widget .
Полностью работоспособен и наиболее полезен режим application, который создаёт динамический класс приложения способом загрузки ХМL ресурса в конструкторе класса. Получается очень компактный прототип для последующей доработки. Доработка обычно заключается в получении ссылки на виджет, изменении свойств виджетов, включая заполнение данными элементов форм и реализацию обработчиков различных событий ( их обычно называют функциями обратного вызова). Большим плюсом такого подхода является возможность изменить визуальное представление формы с помощью pygubu-designer с минимальными изменениями кода программы.
Получаем следующий код и дописываем метод on_ok_clicked.
#!/usr/bin/env python # -*- coding: UTF-8 -*- # pygubu demo # last update : 29.05.2023 09:31:59 # hello world import os import pygubu PROJECT_PATH = os.path.dirname(__file__) PROJECT_UI = os.path.join(PROJECT_PATH, "hello.ui") class HelloApp: def __init__(self): self.builder = builder = pygubu.Builder() builder.add_resource_path(PROJECT_PATH) builder.add_from_file(PROJECT_UI) self.mainwindow = builder.get_object('main') builder.connect_callbacks(self) def on_ok_clicked(self): self.mainwindow.quit() def run(self): self.mainwindow.mainloop() if __name__ == '__main__': app = HelloApp() app.run()
На этом процесс создания приложения закончен.
Два других режима создают последовательность команд для создания интерфейса.
Сама эта возможность неплоха, но код генерируется не вполне корректный. Если вы хорошо знаете tkinter, то и в этом случае вы сможете полученный сценарий доработать до работоспособного состояния. Но в дальнейшем при изменении графического интерфейса придётся заново генерировать код формы, и заново дописывать код для заполнения виджетов данными, функции обратного вызова и т.д.
Пример 2. Получаем ссылки на виджеты и дописываем код
Со своей основной задачей-созданием экранных форм и генерацией прототипа приложения pygubu в основном справляется. Для реализации свойств виджетов и функций обратного вызова вполне достаточно получить ссылку на экземпляр любого виджета формы. Такой функционал позволяет реализовать необходимый код.
Каким образом можно это сделать я попробую показать на следующем примере.
В следующем примере в нашей форме присутствуют следующие виджеты:
listboxBooks - type: tk.Listbox
labelSelBook - type: ttk.Label
scrollbarBooks - type: ttk.Scrollbar
Ссылки на экземпляры виджетов мы можем получить следующим образом:
#get gui widgets self.mainwindow = builder.get_object('toplevel') self.listboxBooks = builder.get_object('listboxBooks') self.labelSelBook = builder.get_object('labelSelBook')
После чего можно использовать экземпляры виджетов самым обычным образом. Например, можно привязать scrollbar к listbox:
# attach scrollbar to listbox self.listboxBooks.config(yscrollcommand=self.scrollbarBooks.set) self.scrollbarBooks.config(command=self.listboxBooks.yview)
И реализовать функцию обратного вызова(call back) при выборе элемента из списка:
def onSelectBook(self, event=None): lbox=event.widget idx=lbox.curselection() bookname=lbox.get(idx) self.labelSelBook['text']=bookname
При первом знакомстве с программой я обнаружил, что не работает, например, привязка скроллбаров к виджeтам. Такой код пришлось добавлять вручную. Последующее изучение программы показало, что задачу автоматичесикого связывания скроллбаров с виджетами решает специальный класс библиотеки pygubu - scrollbarhelper. Его применение оказалось крайне простым. Этот класс выступает контейнером для вложенного в него виджета. В этом случае связывание двух виджетов происходит автоматически.
Заключение
В общем и целом, pygubu уже позволяет создавать графические интерфейсы визуально и получить сравнительно простым способом работающий прототип приложения. Переоценить выгоды тут сложно. Код получается короткий, лаконичный и единообразный, его легко развивать, модифицировать и сопровождать.
Это то самое упрощение работы, которое снижает нагрузку на разработчика и позволяет сосредоточиться на реализации прикладной части.
Кроме того, полагаю, что эта программа будет очень полезна при изучении tkinter. Вы можете визуально поиграть с различными вариантами компоновки, посмотреть свойства виджетов и увидеть их взаимосвязь.