Pyuibuilder -работа с TKinter

Выражаю большую признательность создателю программы Pyuibuilder, Полу.

Моё знакомство с этой программой началось с статьи на Дзене. Меня эта программа заинтересовала прежде всего тем, что она работает с библиотекой TKinter.

PyUIBuilder создает графические приложения, через drag-and-drop. (Drag-and-drop (с англ. «потащи и брось») — способ взаимодействия с элементами (объектами) интерфейса с помощью мыши, тачпада или сенсорного экрана. Это последовательное выполнение на элементах трёх операций: «захвата» (drag), перемещения и «отпускания» (drop) на другую позицию или поверх другого элемента интерфейса). То есть буквально перетаскиваешь элементы мышкой, расставляешь их где нужно, настраиваешь свойства, а на выходе получаешь готовый код на Python.

Так как я много времени уделяю изучению и созданию приложений при помощи стандартной библиотеки Python для GUI TKinter, поэтому я решил посветить эту статью прекрасному проекту PyUIBuilder.

Начнём с Главной странице этого проекта

На странице мы можем скачать приложение, узнать информацию или начать работу в демо версии онлайн.

Рис. 1

На сайте мы можем зарегистрироваться, получить информацию и скачать нужный вариант программы.

Необходимо обязательно зарегистрироваться на сайте.

Давайте скачаем программу и изучим её.

Скачиваем необходимое нам приложение, загружаем в компьютер.

Рис. 2

Открываем программу.

Рис. 3

Ждем открытия программы.

Рис. 4

Разархивируем файл windows-latest.

В папке windows-latest, откроем файл PyUiBuilder-Setup-2.1.2

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

Указать путь до EXE файла установленного на вашем компьютере Python.

Далее Надо указать папку где будет храниться ваш проект созданный в PyUIBuilder.

Рис. 5

Я создал папку 11, и разместил рядом с программой PyUIBuilder

Рис. 6

Вот эту папку (11) я и указал для команды open existing workspace (откройте существующее рабочее пространство).

В ней будет созданна вложенная папка untitled project (проект без названия).

Рис. 7

В ней находится вложенная папка .pyrunner

Рис. 8

Далее находится вложенная папка .venv.

venv — это встроенный в Python модуль для создания виртуального окружения (virtual environment) — изолированного рабочего пространства для проектов.

Рис. 9

В папке .venv находятся несколько пакок и файлов. Изучим их.

Рис. 10

Pyvenv.cfg — это конфигурационный файл, обеспечивающий корректную работу виртуального окружения (venv, virtual environment) в Python.

Папка Scripts. Собственно, содержит содержит скрипты

В папка Lib. Находятся библиотеки необходимые для работы программы.

Папка Include. Место хранения заголовочных файлов.

В дальнейшем появится текстовый файл requirements. Файл requirements.txt в Python нужен для управления зависимостями проекта. Он содержит список Python-пакетов (библиотек), необходимых для работы проекта, и их версий.

Ну и тут будет находится сам исполнительный файл в Python.

Приступим к изучению программы.

Выглядит она так.

Рис. 11

Посмотрим сколько программа поддерживает библиотек Python.

Из выпадающего списка мы можем выбрать tkinter, customTk или Pyside|Pyqt.

Рис. 12

Можем выбрать дневную или ночную тему программы.

Рис. 13

В верхней части программы посмотрим папку, где находится наш проект (папка untitled project).

Рис. 14

Над рабочем полем (холстом) проекта расположены три команды.

Вы можете открыть элементы управления сеткой в левом верхнем углу рядом с иконками удаления

Чтобы включить прикрепление сетки, просто нажмите на кнопку включить кнопку, вы можете отрегулировать размер сетки с помощью ползунка

Вы также можете включить сетки для родительских виджетов, включив сетку виджетов.

1. Вывести виджеты на экран.

2. Чистый холст. Будьте внимательны перед тем как очистить поле проекта.

3. Сетка. Здесь настройки сетки рабочего поля проекта (привязка, показ сетки, цвет,  дополнительная сетка на самом графическом приложении, при помощи бегунка можно выбрать размер сетки).

Рис. 15

Главное меню программы.

File- Файл

Рис. 16

New window- Новое окно. Создаёт новое окно для проекта.

Save desing- Сохранить дизайн. Сохраняет весь проект с графическими настройками.

Load desing- Загрузить дизайн. Загружает ранее созданный проект.

Settings- Настройки. Содержит две настройки. Выбор светлой или темной темы и путь к стартовому файлу Питона.

Logout- Выход из программы.

Exit- Выход

Edit- Редактировать.

Рис. 17

Cut- Вырезать.

Copy- Копировать.

Paste- Вставить.

Select All- Выбрать всё.

View- Смотреть

Рис. 18

Zoom in- Увеличить размер

Zoom out- Уменьшить размер

Reset zoom- Возврат размера

Clear canvas- Очистить полотно. Внимательно отнеситесь к стиранию полотна.

Help- Помощь

Рис. 19

About- О проекте

Documentation- Документация

Community help- Помощь сообщества

Youtubu Tutorial- Инструкция в Ютубе

Report issue- Сообщить о проблеме

Reguest feature- Функция повторного запроса

Share Testimonial- Поделитесь отзывом

Latest Apdates- Последние обновления

License- EULA- Лицензия

Version details- Подробная информация о версии

Также дополнительно дублируется команда File

Рис. 20

Левая боковая панель

Widgets- Виджеты.

Рис. 21

Это отдельные компоненты, такие как метки, кнопки, рамки и т. д., которые помогают вам создавать свой интерфейс.

Plugins. Плагины.

Рис. 22

Самостоятельные элементы дизайна.

Внизу после прокрутки всех списков плагинов, есть команда Request new plugins (запрашивать новые плагины).

Tree view. Древовидный вид.

Рис. 23

Предназначен для отображения иерархических данных как в виде дерева, так и в виде таблицы.

Каждый элемент имеет метку, необязательную иконку и список значений данных.

Значения данных отображаются в последовательных столбцах после метки дерева.

Uploads. Загрузка.

Рис. 24

Можно выбрать файл для загрузки. Актуально для загрузки иконок, картинок.

Templates. Шаблоны.

Рис. 25

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

Code Editor. Редактор кода.

Рис. 26

Включает/выключает редактор кода, который расположен справа в программе.

About. Информация о проекте.

Рис. 27

Discord invite. Приглашение в Discord.

Рис. 28

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

Рис. 29
Рис. 30

Поделитесь информацией и помогите ускорить разработку.

Рис. 31

Docs. Документация о проекте.

Рис. 32

Проект в github.

Рис. 33

Правый верхний угол программы.

Предварительный просмотр.

Рис. 34

Запускает скрипт в Питоне. И открывает созданное приложение.

Редактор кода.

Рис. 35

Редактор кода призван помочь вам писать коды обработчиков событий.

Экспорт кода

Рис. 36

Информация о виде тарифного плана проекта и Логин пользователя.

Рис. 38

Холст

Место, куда вы перетаскиваете виджеты, называется холстом.

Что можно сделать на холсте.

Добавьте виджеты из боковой панели.

Масштабирование и перемещение с помощью мыши.

масштабирование с помощью клавиш +/-

Удаляйте виджеты с помощью del клавиши Enter или щелчка правой кнопкой мыши по виджету (на Mac: Function + Delete).

Для дублирования выбранного виджета можно использовать сочетание клавиш Ctrl/Cmd + D.

Название проекта

По умолчанию все проекты называются “untitled project”, вы можете изменить это в поле ввода заголовка рядом с полем экспорта кода.

Немного кода

Давайте посмотрим код, который создан по умолчанию, без внесения дополнительных виджетов в приложение.  Выше я писал, что создал папку 11, и путь указал на неё. В этой папке создана папка untitled project, далее папка  .pyrunner. В ней вместе с виртуальным окружением и находится файл Питон под названием main.

Посмотрим код:

# This code is generated using PyUIbuilder: https://pyuibuilder.com

import os
import tkinter as tk
from tkinter import ttk

BASE_DIR = os.path.dirname(os.path.abspath(__file__))


main = tk.Tk()
main.title("Main Window")
main.config(bg="#E4E2E2")
main.geometry("700x345")
main.update_idletasks()

geometryX = 0
geometryY = 0

main.geometry("+%d+%d"%(geometryX, geometryY))

menu = tk.Menu(main)
main.config(menu=menu)

menu_0 = tk.Menu(menu, tearoff=0)
menu_0.add_command(label="New", command=lambda: print("New clicked"))
menu_0.add_command(label="Open", command=lambda: print("Open clicked"))
menu.add_cascade(label="File", menu=menu_0)

menu_1 = tk.Menu(menu, tearoff=0)
menu.add_cascade(label="Edit", menu=menu_1)


main.mainloop()

Рассмотрим каждую часть кода.

# This code is generated using PyUIbuilder: https://pyuibuilder.com

Ну здесь понятно, это комментарий.   

import os

import os в Python — это команда, которая импортирует модуль os — встроенную библиотеку для взаимодействия с операционной системой.

Модуль os позволяет выполнять операции с файлами и директориями, получать информацию о файлах и папках (размер, права доступа, время модификации), работать с переменными окружения, выполнять системные команды и запускать дочерние процессы.

import tkinter as tk

import tkinter as tk в Python — это конструкция, которая импортирует модуль Tkinter (библиотеку для создания приложений с графическим интерфейсом, GUI) с именем tk.

from tkinter import ttk

from tkinter import ttk — это команда, которая импортирует модуль ttk (Themed Tk) в библиотеку Tkinter.

Модуль ttk содержит классы более стилизованных и современных виджетов. По умолчанию их внешний вид зависит от операционной системы. Основная идея ttk — отделить оформление виджета от описания его поведения.

BASE_DIR = os.path.dirname(os.path.abspath(__file__))

Переменная __file__ возвращает путь, который был указан при импорте или запуске модуля.

Хотя __file__ является мощным инструментом, его использование в чистом виде может привести к проблемам переносимости. Более надёжный способ — комбинировать __file__ с функциями из модуля os.path.

Строка BASE_DIR = os.path.dirname(os.path.abspath(__file__)) в Python — это комбинация функций из модуля os.path для получения абсолютного пути к директории скрипта. Это позволяет строить все зависимые пути относительно местоположения самого скрипта, а не рабочей директории.

os.path.abspath() — преобразует относительный путь в абсолютный;

os.path.dirname(os.path.abspath(__file__)) позволит получить абсолютный путь к директории скрипта. Это даст возможность строить все зависимые пути относительно местоположения самого скрипта, а не рабочей директории.

Короче это нужно чтобы получить путь к файлу в Python.

main = tk.Tk()

Это команда в библиотеке Tkinter, которая создаёт главное окно приложения.

main.title(“Main Window”)

Метод title() — устанавливает заголовок окна.

main.config(bg=”#E4E2E2″)

Метод config() (configure()) в библиотеке Tkinter (Python) позволяет устанавливать параметры виджета после его создания. Это универсальный метод, который позволяет изменять различные аспекты виджета, такие как его размер, цвет, шрифт и многое другое. В данном случае Background (bg) — устанавливает цвет фона виджета.

main.geometry(“700×345”)

Метод geometry() — устанавливает размеры окна.

main.update_idletasks()

Метод update_idletasks() в библиотеке Tkinter приостанавливает выполнение кода, чтобы выполнить системные фоновые задачи. К ним относятся, например, вывод данных, программно занесённых в компоненты, на экран, перерисовка окна.

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

Важно помнить, что метод update_idletasks() следует использовать только если известно, что делается, так как он может привести к непредсказуемому поведению или циклу. Его не следует вызывать из обработчика событий или функции, которая вызывается из обработчика событий.

geometryX = 0

geometryY = 0

main.geometry(“+%d+%d”%(geometryX, geometryY))

Метод geometry() принимает строку, которая указывает на геометрию окна. В строке могут быть Ширина и высота окна (первые два параметра);

Координаты x и y на экране (последние два параметра).

Размер или координаты могут быть опущены: например, geometry(“600×400”) — только изменить размер, geometry(“+40+80”) — только переместить окно.

Важно: можно передать аргумент-переменную в метод geometry(), но он должен быть в форме (variable1) x (variable2), иначе возникнет ошибка.

Вот как раз здесь и переданы размеры через две переменные geometryX = 0 и geometryY = 0.

menu = tk.Menu(main)

Конструкция menu = tk.Menu(main) в библиотеке Tkinter (Python) создаёт экземпляр виджета Menu — главного меню окна приложения. Меню — это выпадающие списки под словами-пунктами, которые содержат команды, обычно выполняющие какие-либо действия или открывающие диалоговые окна.

main.config(menu=menu)

Метод main.config(menu=menu) в Tkinter позволяет установить меню (экземпляр виджета Menu) для текущего окна.

main.config(menu=menu)

menu — имя экземпляра меню, main — имя окна, на котором оно располагается.

Важно: параметр menu=menu нельзя вставлять, пока меню не будет объявлено и в него не будут введены команды.

menu_0 = tk.Menu(menu, tearoff=0)

Создается меню menu_0 с родителем menu.

Параметр tearoff=0 в строке menu_0 = tk.Menu(menu, tearoff=0) в Tkinter отключает возможность открепления меню от графического окна. По умолчанию значение tearoff — 1, и меню можно открепить с помощью пунктирной линии на границе.

menu_0.add_command(label=”New”, command=lambda: print(“New clicked”))

В коде menu_0.add_command(label=”New”, command=lambda: print(“New clicked”)) в Tkinter — это способ добавить элемент меню (пункт) с меткой «New» и командой, которая при нажатии на этот элемент выводит сообщение «New clicked» в консоль.

Метод add_command позволяет добавлять элементы в меню, задавая параметры: метку (label=”New”), и команду (command=lambda: print(“New clicked”)).

menu_0.add_command(label=”Open”, command=lambda: print(“Open clicked”))

Собственно, тоже что и выше

menu.add_cascade(label=”File“, menu=menu_0)

Метод menu.add_cascade(label=”File”, menu=menu_0) в Tkinter позволяет добавить меню «Файл» (file_menu) в главное меню (menubar). Это метод из класса виджета Menu, который позволяет создавать подменю и иерархически организовывать структуру меню.

Собственно мы сперва создали разделы меню New и Open, а потом привязали эти разделы к меню File.

Рис. 38

menu_1 = tk.Menu(menu, tearoff=0)

menu.add_cascade(label=”Edit”, menu=menu_1)

Собственно, здесь создали следующий раздел Меню и добавили раздел Edit.

Рис. 39

Некие зависимости создания подменю

Рис. 40

main.mainloop()

Метод в библиотеке Tkinter (Python), который запускает бесконечный цикл обработки событий в приложении.

Он позволяет запускать приложение, ждать возникновения событий (нажатий клавиш, кликов мыши, изменения размера окна) и обрабатывать их, пока окно не закрыто.

Наконец-то закончили изучение стартового кода.

Вернёмся к изучению программы

Открытие и создание проекта

При повторном открытии программы откроется окно выбора рабочей области.

Рис. 41

Мы можем открыть ранее созданный проект выбрав команду “Откройте существующее рабочее пространство”. Надо выбрать папку 11, где и находится проект untitled project и выбрать его.

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

Рис. 42

Как и писал выше проекты у меня в папке 11, казав её в качестве папки рабочей области и изменив в названии на untitled project2 у меня при открытии программы появится новая папка (рис. 42).

Программа папки не перезаписывает проекты с одинаковым названием, приходится создавать проекты с новым названием.

Создание меню

Если навести курсор на поле с названиями разделов меню, то появится настройки по созданию новых разделов Меню.

Рис. 43

И также создание вложенных подразделов Меню.

Тут всё интуитивно, можно прибавить, удалить и корректировать созданные разделы меню.

Рис. 44

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

Виджеты

Каждый виджет имеет свои собственные атрибуты, некоторые из которых могут быть общими.

Главное окно: Каждый пользовательский интерфейс должен иметь одно главное окно. Если у вас нет главного окна, вывод не будет сгенерирован.

Если у вас несколько главных окон, при генерации кода вам будет предложено удалить одно из них.

Нажав на виджет, мы получим настройки и атрибуты этого виджета.

Все атрибуты виджетов доступны на панели инструментов. Панель инструментов содержит сворачиваемые элементы, которые можно открыть для изменения атрибутов виджетов, таких как цвет переднего/заднего плана, темы и многое другое.

Рис. 45

Настройки и атрибуты Главного окна.

Рис. 46

Layout- Расположение (здесь он переведён как Макеты)

 Каждый виджет, который может содержать дочерний виджет, имеет три различных варианта расположения. По умолчанию absolute- Абсолютное/Местоположение (гибкое) .

Flex (также известный как pack)

Grid- Сетка

Place- По месту

Рис. 47

Родительские виджеты управляют компоновкой. Свойства компоновки, такие как положение в сетке, будут доступны дочерним виджетам в разделе grid-manager/flex-manager.

Добавление изображений к метке

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

Рис. 49

Теперь в разделе «Атрибуты метки» вы увидите опцию загрузки изображения. Выберите изображение из выпадающего списка.

Загруженные картинки будут видны в разделе Загрузки

Рис. 50

Добавим в настройках Window Logo уже загруженную иконку (иконку загрузил маленькую размером  16х16).

Рис. 51

Иконка появилась в макете

Рис. 52

Кстати загруженные картинки находятся в папках untitled project- .pyrunner- assets.

Event Handlers. Обработчики событий

Выберем раздел Event Handlers. Обработчики событий- Add Event (Добавить событие)

Рис. 53

Появятся два поля для выбора

Рис. 54

В верхнем поле из выпадающего списка, выбираем вид события

Рис. 55
Рис. 56

Выбираем в качестве события “Нажатие левой кнопки мыши”.

Рис. 57

Изменим код в редакторе кода.

Уберем заглушку pass для функции. Напишем тело функции print(“Privet”).

Рис. 58

В нижнем окне появляется название функции, её и выбираем

Рис. 59

Посмотрим на код.

У нас появилась функция click_handler.

def click_handler(event):

                print(“Privet”)

Появился вызов функции

 main.bind(“<Button-1>”, click_handler)

с событием для обработки левого нажатия кнопки мыши <Button-1>.

Рис. 60

Обратите внимание.

Выше мы добавили иконку для заголовка.

Появился код. Для добавления изображения иконки.

main_img = Image.open(os.path.join(BASE_DIR, “assets”, “images”, “269295_pie-chart-icon.png”))

main_img = ImageTk.PhotoImage(main_img)

Добавим кнопку в приложение

Рис. 61

Добавим событие к кнопке.

Перетаскиваем кнопку из списка виджетов. Выделяем кнопку в приложении.

Рис. 62

Выбираем тип события. Меняем название функции. При необходимости меняем выполнение функции.

Новая функция появляется в списке функций. Выбираем её.

И получаем ошибку.

Необходимо в редакторе кода. Прописывать все используемые функции в этом проекте.

И тогда в выпадающем списке будут отображаться все используемые функции.

Рис. 63

Кстати, если мы добавим в редактор кода еще одну функцию click_handler0 для события и не будем вызывать событие. То ошибки при компиляции не будет.

Рис. 64

Layout. Макеты

Выбрать можно в вкладки Layout.

Существует 4 основных макета. Макеты задаются родительскими виджетами. После установки макета каждый дочерний виджет будет использовать один и тот же макет для позиционирования. Единственное исключение — если вы включили абсолютное позиционирование на панели инструментов дочерних виджетов.

По умолчанию стоит значение absolute (абсолютный).

Если мы перетащим две кнопки в наше приложение. То можно передвигать расположение кнопок произвольно.

Рис. 65

Посмотрим, что у нас с кодом?

Рис. 66

Здесь и нас позиционирование. Place. Немного информации об этом методе.

Метод place() позволяет более точно настроить координаты и размеры виджета. Он принимает следующие параметры:

height и width: устанавливают соответственно высоту и ширину элемента в пикселях

relheight и relwidth: также задают соответственно высоту и ширину элемента, но в качестве значения используется число float в промежутке между 0.0 и 1.0, которое указывает на долю от высоты и ширины родительского контейнера

x и y: устанавливают смещение элемента по горизонтали и вертикали в пикселях соответственно относительно верхнего левого угла контейнера

relx и rely: также задают смещение элемента по горизонтали и вертикали, но в качестве значения используется число float в промежутке между 0.0 и 1.0, которое указывает на долю от высоты и ширины родительского контейнера

bordermode: задает формат границы элемента. Может принимать значение INSIDE (по умолчанию) и OUTSIDE

anchor: устанавливает опции растяжения элемента. Может принимать значения n, e, s, w, ne, nw, se, sw, c, которые являются сокращениями от North(север – вверх), South (юг – низ), East (восток – правая сторона), West (запад – левая сторона) и Center (по центру). Например, значение nw указывает на верхний левый угол

Выберем в вкладки Layout значение Flex.

Перенесём две кнопки. Но выделив одну кнопку, выберем из атрибутов этой кнопки раздел Absolute positioning, подтвердим галочкой выбор.

Рис. 67

Посмотрим код.

Рис. 68

Мы видим, что у одной кнопки значение позиционирования pack.

Этот метод принимает следующие параметры:

expand: если равно True, то виджет заполняет все пространство контейнера.

fill: определяет, будет ли виджет растягиваться, чтобы заполнить свободное пространство вокруг. Этот параметр может принимать следующие значения: NONE (по умолчанию, элемент не растягивается), X (элемент растягивается только по горизонтали), Y (элемент растягивается только по вертикали) и BOTH (элемент растягивается по вертикали и горизонтали).

anchor: помещает виджет в определенной части контейнера. Может принимать значения n, e, s, w, ne, nw, se, sw, c, которые являются сокращениями от Noth(север – вверх), South (юг – низ), East (восток – правая сторона), West (запад – левая сторона) и Center (по центру). Например, значение nw указывает на верхний левый угол

side: выравнивает виджет по одной из сторон контейнера. Может принимать значения: TOP (по умолчанию, выравнивается по верхней стороне контейнера), BOTTOM (выравнивание по нижней стороне), LEFT (выравнивание по левой стороне), RIGHT (выравнивание по правой стороне).

ipadx: устанавливает отступ содержимого виджета от его границы по горизонтали.

ipady: устанавливают отступ содержимого виджета от его границы по вертикали.

padx: устанавливает отступ виджета от границ контейнера по горизонтали.

pady: устанавливает отступ виджета от границ контейнера по вертикали.

Ну а у второй кнопки стало значение place (это позиционирование мы описали выше).

Выберем в Главном окне в разделе Layout, позиционирование Grid (сетка)

при этом в подразделе Direction выберем Horizontal. В подразделе Gap стоит значение 10.

Рис. 69

Посмотрим код.

Рис. 70

Мы видим что позиционирование у кнопок стало типа grid.

Метод grid() позволяет поместить виджет в определенную ячейку условной сетки или грида.

Метод grid применяет следующие параметры:

column: номер столбца, отсчет начинается с нуля

row: номер строки, отсчет начинается с нуля

columnspan: сколько столбцов должен занимать элемент

rowspan: сколько строк должен занимать элемент

ipadx и ipady: отступы по горизонтали и вертикали соответственно от границ элемента до его содержимого

padx и pady: отступы по горизонтали и вертикали соответственно от границ ячейки грида до границ элемента

sticky: выравнивание элемента в ячейке, если ячейка больше элемента. Может принимать значения n, e, s, w, ne, nw, se, sw, которые указывают соответствующее направление выравнивания

Есть дополнительные настройки для этого позиционирования

Рис. 71
Рис. 72

Ну и выберем последнее значение в Главном окне в разделе Layout, позиционирование Place

Перенесём кнопки в приложение

Посмотрим код.

Рис. 73

Видим, что что кнопки имеют позиционирование pack.

При этом кнопки не имеют в настройках раздел Absolute positioning.

Все остальные атрибуты и настройки прекрасно мною описаны в разделе описания TKinter.

Сохранение проекта

При желании, можем сохранить проект. Выберем раздел главного меню- File-Save design.

Далее выбираем папку, в которую хотим сохранить проект. Проект будет сохранён в формате pyui.