Pythonでクロスプラットフォームなアプリが作れる「Flet」を試す (original) (raw)
Flet controls
https://flet.dev/docs/getting-started/flet-controls
FletのUIは、controls(通称: ウィジェット)で構成される。controlsはPage
または他のcontrolsの中に配置する。Page
が最上位のcontrolになり、controlsをネストしていくとPageがルートになるツリー構造として、UIが構成される。
controlsはPythonのクラスになっているので、以下のようにインスタンスを作成することで利用できる。そしてPageにcontrolsを追加、Pageを更新することで反映される。
import flet as ft
def main(page: ft.Page):
# controlを初期化
t = ft.Text(value="Hello, world!", color="green", size=30)
# pageに追加
page.controls.append(t)
# pageを更新
page.update()
ft.app(main)
$ flet run -d -r my_flet_app
page.update()
を使うとcontrolのプロパティおよびUIを更新できる。
import flet as ft
import time
def main(page: ft.Page):
t = ft.Text(size=30)
page.add(t) # page.controls.append(t) および page.update() のショートカット
for i in range(100):
t.value = f"Step {i}"
page.update()
time.sleep(1)
ft.app(main)
Page
のように、他のcontrolを含むことができる「コンテナ」としてのcontrolもある。
row
だと横に並べる
import flet as ft
def main(page: ft.Page):
page.add(
ft.Row(controls=[
ft.TextField(label="Your name"),
ft.ElevatedButton(text="Say my name!")
])
)
ft.app(main)
Column
だと縦に並べる、といった感じ。
import flet as ft
def main(page: ft.Page):
page.add(
ft.Column(controls=[
ft.TextField(label="Your name"),
ft.ElevatedButton(text="Say my name!")
])
)
ft.app(main)
page.update()
は最後に実行されてから変更があった部分だけを更新するようになっているので、controlをまとめて更新してからpage.update()
一発で変更できる。
import flet as ft
import time
def main(page: ft.Page):
for i in range(100):
page.controls.append(ft.Text(f"Line {i}", size=20))
if i > 4:
page.controls.pop(0)
page.update()
time.sleep(0.5)
ft.app(main)
ボタンなどのcontrolにはイベントハンドラを設定できる。
import flet as ft
import time
def main(page: ft.Page):
def button_clicked(e):
page.add(ft.Text("クリックされました!", size=30))
page.add(ft.ElevatedButton(text="クリックしてね", on_click=button_clicked))
ft.app(main)
これを使ってシンプルなTo-Doアプリの例が載っている。
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()
page.update()
new_task = ft.TextField(hint_text="ToDoを入力", width=300)
page.add(ft.Row([new_task,ft.ElevatedButton("追加", on_click=add_clicked)]))
ft.app(main)
こんなことが書いてある、なるほど、今の自分にはこのほうがわかりやすいかもしれない。
Fletは、ステートフルコントロールを使用して「手動」でアプリケーションのUIを構築し、コントロールのプロパティを更新することでそれを変更する、命令型UIモデルを実装している。Flutterは、アプリケーションデータの変更時にUIが自動的に再構築される宣言型モデルを実装している。最新のフロントエンドアプリケーションにおけるアプリケーションの状態管理は、本質的に複雑な作業であり、Fletの「旧式」のアプローチは、フロントエンドの経験のないプログラマーにとってはより魅力的である可能性がある。
visible
/disabled
プロパティ
controlの可視性や操作可否をコントロールすることができるプロパティ。なお、子要素がある場合はそれも含めて制御される。
visible
を使うと表示・非表示を切り替えれる。デフォルトはTrue
(表示する)。
import flet as ft
def main(page: ft.Page):
def toggle_visible(e):
if t.visible == True:
t.visible = False
button.text = "visible!"
else:
t.visible = True
button.text = "invisible!"
page.update()
button = ft.ElevatedButton("invisible!", on_click=toggle_visible)
t = ft.Text(value="Hello, world!", color="green", size=30)
page.add(ft.Column([button, t]))
page.update()
ft.app(main)
disabled
を使うとデータ入力に関するコントロールの操作、例えば入力・変更等の可否を切り替えれる。デフォルトはFalse
(コントロール可能)。
import flet as ft
def main(page: ft.Page):
def toggle_disabled(e):
if t.disabled == True:
t.disabled = False
button.text = "disable!"
else:
t.disabled = True
button.text = "enable!"
page.update()
button = ft.ElevatedButton("disable", on_click=toggle_disabled)
t = ft.TextField(hint_text="enter something...", width=300)
page.add(ft.Column([button, t]))
page.update()
ft.app(main)
あとはボタン・テキストボックス・チェックボックス・ドロップダウンなどを使ったイベントハンドラのサンプルコートが並んでる。
ボタンをクリックしたら増減するカウンター。
import flet as ft
def main(page: ft.Page):
page.title = "カウンターのサンプル"
page.vertical_alignment = ft.MainAxisAlignment.CENTER
txt_number = ft.TextField(value="0", text_align="right", width=100)
def minus_click(e):
txt_number.value = str(int(txt_number.value) - 1)
page.update()
def plus_click(e):
txt_number.value = str(int(txt_number.value) + 1)
page.update()
page.add(
ft.Row(
[
ft.IconButton(ft.icons.REMOVE, on_click=minus_click),
txt_number,
ft.IconButton(ft.icons.ADD, on_click=plus_click),
],
alignment=ft.MainAxisAlignment.CENTER,
)
)
ft.app(main)
名前を入力したら挨拶が表示される。
import flet as ft
def main(page):
def btn_click(e):
if not txt_name.value:
txt_name.error_text = "名前を入力してください"
page.update()
else:
name = txt_name.value
page.clean()
page.add(ft.Text(f"こんにちは、{name} さん!"))
txt_name = ft.TextField(label="あなたの名前")
page.add(txt_name, ft.ElevatedButton("挨拶する", on_click=btn_click))
ft.app(main)
フォーカスが当たるとプレースホルダーの文字がラベルっぽくなるの良いね
何も入力せずにボタンクリックするとこうなる
チェックボックスに連動して、チェックボックスの状態をテキストで出力
import flet as ft
def main(page):
def checkbox_changed(e):
output_text.value = (
f"スキーを習得した? : {todo_check.value}."
)
page.update()
output_text = ft.Text()
todo_check = ft.Checkbox(label="ToDo: スキーの習得", value=False, on_change=checkbox_changed)
page.add(todo_check, output_text)
ft.app(main)
ドロップダウンリストの選択値を取得して表示
import flet as ft
def main(page: ft.Page):
def button_clicked(e):
output_text.value = f"リストから選択された色: {color_dropdown.value}"
page.update()
output_text = ft.Text()
submit_btn = ft.ElevatedButton(text="送信", on_click=button_clicked)
color_dropdown = ft.Dropdown(
width=100,
options=[
ft.dropdown.Option("赤"),
ft.dropdown.Option("緑"),
ft.dropdown.Option("青"),
],
)
page.add(color_dropdown, submit_btn, output_text)
ft.app(main)