Гайд по Flet: приступая к работе. Создание приложений на Python

Пост опубликован в блогах iXBT.com, его автор не имеет отношения к редакции iXBT.com
| Гайд | Программы, сервисы и сайты

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

Чтобы написать Flet приложение, Вам не нужно быть front-end гуру, но рекомендуется знать основы Python и объектно-ориентированного программирования.

Автор: donanimhaber.com Источник: www.donanimhaber.com

Установка модуля Flet

Flet требует Python 3.7 или выше. Для начала Вам нужно установить модуль flet. Для этого в терминале (командной строке) напишите:

pip install flet

Чтобы установить пре-релиз Flet (для продвинутых пользователей), напишите в терминале (командной строке):

pip install flet –pre

ОСТОРОЖНО. Мы рекомендуем устанавливать пре-релизные сборки в виртуальную среду.

Linux

Для запуска Flet приложений на Linux и WSL требуется установленная библиотека GStreamer. Скорее всего, у Вас уже она установлена, но если Вы получаете error while loading shared libraries: libgstapp-1.0.so.0: cannot open shared object file: No such file or directory во время работы приложения Flet, Вам нужно установить GStreamer.

Чтобы установить GStreamer на Ubuntu/Debian пропишите в терминале следующие команды:

sudo apt-get update
sudo apt-get install libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-doc gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio

Посмотрите этот гайд для установки на остальные Linux дистрибутивы.

WSL

Flet приложения могут быть запущены на WSL2. Если Вы получаете ошибку cannot open display, следуйте этому руководству по устранению неполадок.

Стандартная структура приложения

Самое минимальное Flet приложение имеет следующую структуру:

import flet as ft

def main(page: ft.Page):
    # add/update controls on Page
    pass

ft.app(target=main)

ЗАМЕТКА. Этот раздел назван «базовым», поскольку позже в этом гайде, мы рассмотрим более реалистичные подходы к структуре приложения с многократно используемыми элементами управления.

Типичная Flet программа заканчивается вызовом flet.app(), где приложение начинает ожидать новые пользовательские сессии. Функция main() — точка входа в Flet приложении. Она вызывается в новом потоке для каждой пользовательской сессии с переданным в неё экземпляром Page (страница). При запуске Desktop приложения, создаётся только одна сессия.

Page подобен «canvas» — особенному для пользователя визуальному состоянию пользовательской сессии. Чтобы создать пользовательский интерфейс приложения, Вы добавляете и удаляете элементы управления на страницу, обновляете их свойства. Приведенный выше пример кода будет отображать каждому пользователю просто пустую страницу.

По умолчанию Flet приложение запускается в нативном окне операционной системы, что очень удобно для разработки. Однако, Вы можете открыть его в новом окне браузера, изменив вызов flet.app следующим образом:

ft.app(target=main, view=ft.WEB_BROWSER)

ИНФОРМАЦИЯ. Внутри, каждое Flet приложение является веб-приложением, и даже если оно открыто в нативном окне ОС, встроенный сервер запускается в фоновом режиме. Flet веб-сервер называется «Fletd» и по умолчанию прослушивает случайный TCP-порт. Вы можете указать случайный TCP-порт, а затем открыть приложение в браузере вместе с десктопным окном:

flet.app(port=8550, target=main)

Откройте http://localhost:<port> в Вашем браузере, чтобы увидеть Ваше Flet приложение

Элементы управления

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

Элементы управления — это просто обычные классы Python. Создавайте экземпляры элементов управления, используя конструкторы с параметрами, соответствующими их свойствам, например:

t = ft.Text(value="Hello, world!", color="green")

Чтобы отобразить элемент управления на страницу, добавьте его в список элементов управления и вызовите call.update(), чтобы отправить изменения страницы в браузер или десктопный клиент:

import flet as ft

def main(page: ft.Page):
    t = ft.Text(value="Hello, world!", color="green")
    page.controls.append(t)
    page.update()

ft.app(target=main)

ЗАМЕТКА. В следующих примерах мы будем показывать только содержимое функции main

Вы можете изменять свойства элементов управления и интерфейс будет обновлён со следующим вызовом page.update():

t = ft.Text()
page.add(t) # it's a shortcut for page.controls.append(t) and then page.update()

for i in range(10):
    t.value = f"Step {i}"
    page.update()
    time.sleep(1)

Некоторые элементы управления являются «контейнерами» (например, Page), которые могу содержать другие элементы управления. Например, элемент управления Row позволяет расположить другие элементы управления в ряд один за другим:

page.add(
    ft.Row(controls=[
        ft.Text("A"),
        ft.Text("B"),
        ft.Text("C")
    ])
)

Или TextField и ElevatedButton рядом:

page.add(
    ft.Row(controls=[
        ft.TextField(label="Your name"),
        ft.ElevatedButton(text="Say my name!")
    ])
)

page.update() достаточно умный, чтобы отправлять изменения, сделанные только с момента его последнего вызова, поэтому Вы можете добавить пару новых элементов управления на страницу, удалить некоторые из них, изменить свойства других элементов управления, а затем вызвать page.update() для пакетного обновления, например:

for i in range(10):
    page.controls.append(ft.Text(f"Line {i}"))
    if i > 4:
        page.controls.pop(0)
    page.update()
    time.sleep(0.3)

Некоторые элементы управления, такие как кнопки, могут иметь хендлеры, реагирующие на пользовательский ввод, например ElevatedButton.on_click:

def button_clicked(e):
    page.add(ft.Text("Clicked!"))

page.add(ft.ElevatedButton(text="Click me", on_click=button_clicked))

И более сложный пример для простого списка дел:

import flet as ft

def main(page):
    def add_clicked(e):
        page.add(ft.Checkbox(label=new_task.value))
        new_task.value = ""
        new_task.focus()
        new_task.update()

    new_task = ft.TextField(hint_text="Whats needs to be done?", width=300)
    page.add(ft.Row([new_task, ft.ElevatedButton("Add", on_click=add_clicked)]))

ft.app(target=main)

ИНФОРМАЦИЯ. Flet реализует императивную модель пользовательского интерфейса, в которой Вы «вручную» создаете пользовательский интерфейс с отслеживающими состояние элементами управления, а затем изменяете его, обновляя свойства объекта. Flutter реализует декларативную модель, в которой пользовательский интерфейс автоматичкески перестраивается при изменении данных приложения. Управление состоянием приложения в современных front-end приложениях по своей сути является сложной задачей, и подход Flet «старой школы» может быть более привлекательным для программистов, не имеющих опыта работы с интерфейсом.

Свойство visible

У каждого элемента управления есть свойство visible, в котором по умолчанию установлено true — элемент управления отображается на странице. Установка visible на false полностью прекращает отображение элемента (и всех его дочерних элементов, если таковые имеются) на странице. Скрытые элементы управления нельзя сфокусировать или выбрать с помощью клавиатуры или мыши, и они не генерируют никаких событий.

Свойство disabled

У каждого элемента управления есть свойство disabled, в котором по умолчанию установлено false — элемент управления и все его дочерние элементы активны. Свойство disabled чаще всего используется с элементами управления ввода данных, такие как TextField, Dropdown, Checkbox, кнопки. Однако значение disabled может быть установлено у родительского элемента управления, и его значение будет рекурсивно передаваться всем дочерним элементам.

Например, если у Вас есть форма с элементом управления множественным вводом, вы можете установить свойство disabled для каждого элемента управления в отдельности:

first_name = ft.TextField()
last_name = ft.TextField()
first_name.disabled = True
last_name.disabled = True
page.add(first_name, last_name)

Или Вы можете вставить элементы управления формы в контейнер, например, Column и установить значение disabled для него.

first_name = ft.TextField()
last_name = ft.TextField()
c = ft.Column(controls=[
    first_name,
    last_name
])
c.disabled = True
page.add(c)

Ссылки для элементов управления

Элементы управления Flet — это объекты и для доступа к их свойствам, нам нужны ссылки (переменные) к этим объектам.

Рассмотрим следующий пример

import flet as ft

def main(page):

    first_name = ft.TextField(label="First name", autofocus=True)
    last_name = ft.TextField(label="Last name")
    greetings = ft.Column()

    def btn_click(e):
        greetings.controls.append(ft.Text(f"Hello, {first_name.value} {last_name.value}!"))
        first_name.value = ""
        last_name.value = ""
        page.update()
        first_name.focus()

    page.add(
        first_name,
        last_name,
        ft.ElevatedButton("Say hello!", on_click=btn_click),
        greetings,
    )

ft.app(target=main)

В самом начале метода main(), мы создаём 3 элемента управления, которые собираемся использовать в хендлере on_click кнопки: 2 TextField для имени и фамилии и Column — контейнер для приветственных сообщений. Мы создаём элементы управления со всеми установленными для них свойствами и в конце метода main(), в вызове функции page.add(), мы используем их ссылки (переменные).

Когда добавляется всё больше и больше элементов управления и ивент хендлеров, становится сложно хранить все ссылки в одном месте, поэтому они становятся разбросанными по всему телу main(). Взглянув на параметры page.add(), трудно представить(без постоянного перехода к определениям переменных в IDE) как выглядела бы конечная форма.

    page.add(
        first_name,
        last_name,
        ft.ElevatedButton("Say hello!", on_click=btn_click),
        greetings,
    )

first_name — это TextField, у него есть автофокус? Приветствие является Row или Column?

Flet предоставляет служебный класс Ref, который позволяет определить ссылку на элемент управления, использовать эту ссылку в ивент хендлерах и устанавливать ссылку на реальный элемент управления позже, при построении дерева. Идея пришла от React

Чтобы определить новую типизированную ссылку на элемент управления:

first_name = ft.Ref[ft.TextField]()

Чтобы получить доступ к элементу управления, на который ссылается ссылка (отмена ссылки на элемент управления), используйте свойство Ref.current:

# empty first name
first_name.current.value = ""

Чтобы присвоить элементу управления ссылку, установите в свойство Control.ref ссылку:

page.add(
    ft.TextField(ref=first_name, label="First name", autofocus=True)
)

ЗАМЕТКА. У всех элементов управления Flet есть свойство ref.

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

import flet as ft


def main(page):

    first_name = ft.Ref[ft.TextField]()
    last_name = ft.Ref[ft.TextField]()
    greetings = ft.Ref[ft.Column]()

    def btn_click(e):
        greetings.current.controls.append(
            ft.Text(f"Hello, {first_name.current.value} {last_name.current.value}!")
        )
        first_name.current.value = ""
        last_name.current.value = ""
        page.update()
        first_name.current.focus()

    page.add(
        ft.TextField(ref=first_name, label="First name", autofocus=True),
        ft.TextField(ref=last_name, label="Last name"),
        ft.ElevatedButton("Say hello!", on_click=btn_click),
        ft.Column(ref=greetings),
    )

ft.app(target=main)

Теперь, мы можем ясно видеть в page. add() структуру страницы и все элементы управления, из которых она построена.

Да, логика становится немного подробнее, так как Вам приходится использовать.current. для доступа к элементу управления по ссылке, но это вопрос личных предпочтений :)

Источник: Python guide | Getting started

Автор не входит в состав редакции iXBT.com (подробнее »)
Об авторе
Человек, который считает себя программистом

4 комментария

113404987599120471675@google
Для начала стоило бы написать что такое этот flet и зачем это вообще нужно
3177759@vkontakte
Кто сюда попал и так знает что такое Flet, а вот лишняя вода только напрягает. Куда не зайди чтоб получить конкретную информацию — сначала заставляют прочитать 5 книг и так известной теории и потом только дают ответ в 2 строчки
107371094140935500836@google
Cпасибо за полезную статью!
Пытаюсь создать сайт/приложение. Увидел вот информацию о Flet, показалось очень перспективным.
Есть ли ещё подобные статьи? Или ресурсы? Где можно было бы получить информацию о работе с Flet.
110046234658040970972@google
Как заставить эти приложения работать в бровзере на андроид?

Добавить комментарий

Сейчас на главной

Новости

Публикации

Первый гревел Shulz: изучаем прототип велосипеда The Lightning

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

С какой скоростью надо ездить по лужам

В дождливую погоду дороги становятся особенно коварными, а лужи на асфальте — не просто лужи, а настоящие испытания для водителя и его автомобиля. Каждая такая встреча скрывает риски: от...

Почему на современных стиральных машиных нельзя отключить отжим, и как это исправить вручную

Если на моделях стиральных машин 7-10 летней давности управление оборотами отжима (вплоть до 0) было базовой возможностью, то у современной техники подобная функция встречается всё реже. Но для...

Как можно узнать, сколько герц в экране Айфона и на что они влияют

В мире смартфонов происходит настоящая революция, связанная с частотой обновления экранов. Долгое время стандартом считались 60 Гц, но теперь производители, включая Apple, переходят на более...

Как одеваться в жаркую погоду, чтобы было комфортно

Лето — пора яркого солнца и прогулок на свежем воздухе. Но высокая температура может стать настоящим вызовом, если тщательно не продумать образ. Поговорим о том, как правильно одеваться...

Обзор MobaPad M6S: максимально удобная альтернатива Joy-Conn для Nintendo Switch

Над альтернативой для штатных Joy-Conn игровой консоли Nintendo Switch работали сразу несколько производителей, причем относительного успеха добился каждый из них, но по возможностям лучше, чем...