【完全版】Fletで最初に知っておくとよさそうな基礎を全部まとめてみた

Featured image of the post

はじめに

Pythonのフレームワーク「Flet」について一から調べたので、備忘録として最初に知っておくとよさそうな基本知識をまとめてみた😊

この記事で解決したいこと

はじめてFlet開発するときに困らないようにする!

  • Fletの基本概念
  • 画面の作り方
  • 画面の制御

今回のゴール

✅基礎知識を把握し、前回作ったカウンターアプリの仕組みを理解できるようになる!

Image in a image block

【補足】カウンターアプリのソースコード

counter.py

import flet as ft

def main(page: ft.Page):
    page.title = "Flet counter example"
    page.vertical_alignment = ft.MainAxisAlignment.CENTER

    txt_number = ft.TextField(value="0", text_align=ft.TextAlign.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(target=main)

Fletの概念を理解する

前回作ったカウンターアプリを例に基本的な概念を理解していく😊

プログラムの基本構成

✅とりあえずエントリーポイントを用意すれば起動できる。

  • ft.app(target=任意の関数名)でエントリーポイントが設定できる。

カウンターアプリの場合
import flet as ft

def main(page: ft.Page):
		# TODO:ここに処理を書く
    # ボタンの追加とか

# ✅エントリーポイントはmainとする
ft.app(target=main)

簡単なプログラムなら1ファイルだけで完結する

画面と処理を同一ファイルに書くことができ、簡単なアプリなら1ファイルで作れる。

カウンターアプリの場合

counter.pyという1つのファイルだけで作られている。

Image in a image block

画面の1パーツ = コントロールと呼ぶ

✅「テキスト」「ボタン」などのパーツをコントロールと呼ぶ。

1コントロールで改行される

例:textコントロール × 3

Image in a image block

💡
「テキストコントロールを3つ生成したら、横幅が余っていても勝手に改行されて3行になるよ」ということ。

ただしRowなど一部のコントロールは入れ子にできる

例:Rowの中にtextが3つ入っている

Image in a image block

カウンターアプリの場合

「Row」の中に「ボタン」と「テキスト」が配置されている(入れ子)。

Image in a image block

💡
どんなコントロールがあるか?は公式ドキュメントに記載されている。

https://flet.dev/docs/controls

pageとview

✅アプリには必ずpageとviewが存在する。

Image in a image block

引用:https://flet.dev/blog/navigation-and-routing/#page-views

page

✅画面全体を管理するもの

💡
viewの管理などもしている!

pageのプロパティ一覧
💡
この表は公式ドキュメントを翻訳してまとめたものです。不明な点があれば公式ドキュメントをご確認ください。

https://flet.dev/docs/controls/page

プロパティ名概要
auto_scroll子要素が更新されたときにスクロールバーの位置を自動的に移動するかどうかを指定する。Falseにすると、scroll_to()メソッドが使える。
app_barページの上部に表示するAppBarコントロールを指定する。
bannerページの上部に表示するBannerコントロールを指定する。
bgcolorページの背景色を指定する。色の値は16進数やflet.colorsモジュールの名前で指定できる。
client_ipWebでのみ有効。接続しているユーザーのIPアドレスを取得できる。
client_user_agentWebでのみ有効。接続しているユーザーのブラウザの詳細を取得できる。
controlsページに表示するControlのリストを指定する。page.controls.append()やpage.add()で追加できる。
dark_themeダークテーマをカスタマイズするためにtheme.Themeのインスタンスを指定する。
dialog表示するAlertDialogコントロールを指定する。
floating_action_buttonページの内容の上に表示するFloatingActionButtonコントロールを指定する。
fontsカスタムフォントをインポートして、Text.font_familyやtheme.font_familyで使えるようにするために、フォント名とフォントファイルのURLの辞書を指定する。フォントファイルは外部リソースやアプリケーションアセットからインポートできる。
heightWebページやネイティブOSウィンドウの内容領域の高さを取得できる。このプロパティは読み取り専用で、page.on_resizeハンドラーでよく使われる。
horizontal_alignment子要素を水平方向にどのように配置するかを指定する。デフォルト値はCrossAxisAlignment.STARTで、ページの左側に配置されることを意味する。プロパティ値はCrossAxisAlignment列挙型で、以下の値がある:
START (default)
CENTER
END
STRETCH
BASELINE
on_scroll_intervalon_scrollイベントの間引き時間(ミリ秒)を指定する。デフォルトは10.
overlayページの内容の上に重ねて表示するControlのリストを指定する。
paddingページの内容とその端との間隔を指定する。デフォルト値は各辺から10ピクセルである。ゼロパディングに設定するには:page.padding = 0. 詳細と可能な値については、Container.paddingを参照してください。
platformアプリケーションが動作しているオペレーティング・システム:
ios
android
macos
linux
windows
pubsubアプリケーションセッション間でメッセージをやり取りするためのシンプルなPubSub実装です。
pwaアプリケーションがProgressive Web App (PWA)として実行されているかどうかを示す真偽値です。読み取り専用です。
routeページのナビゲーションルートを取得または設定します。ナビゲーションとルーティングのセクションで詳細と例を参照してください。
rtlテキストの方向を右から左に設定するかどうかを指定します。デフォルトはFalseです。
scrollページに垂直方向のスクロールを有効にして、内容のオーバーフローを防ぎます。プロパティ値はオプションのScrollMode列挙型で、Noneがデフォルトです。

None (デフォルト) - Rowはスクロールできず、内容がオーバーフローする可能性がある。
AUTO - スクロールが有効で、スクロールバーはスクロール時にのみ表示される。
ADAPTIVE - スクロールが有効で、スクロールバーはWebやデスクトップでアプリを実行しているときに常に表示される。
ALWAYS - スクロールが有効で、スクロールバーは常に表示される。
HIDDEN - スクロールが有効だが、スクロールバーは常に隠れている。
session_idユーザーセッションの一意なIDです。このプロパティは読み取り専用です。
spacingページ上のコントロール間の垂直方向の間隔を指定します。デフォルト値は10ピクセルです。間隔は、alignmentがstart, end, centerの場合にのみ適用されます。
splashページの内容の上に表示するControlを指定します。ProgressBarやProgressRingなどを使って、長時間かかる操作のインジケーターとして使えます。
show_semantics_debuggerフレームワークが報告するアクセシビリティ情報を表示するオーバーレイを有効にするかどうかを指定します。
themeライトテーマをカスタマイズするためにtheme.Themeのインスタンスを指定します。現在、テーマは「シード」色から自動的に生成されることしかできません。
theme_modeページのテーマ。
プロパティの値はオプションのThemeMode列挙型で、デフォルトはSYSTEMです。
サポートされる値:SYSTEM(デフォルト)、LIGHTまたはDARK。
title例えば、ブラウザやネイティブOSのウィンドウのタイトル
vertical_alignment子要素の縦方向の設定。
例えば、デフォルトの MainAxisAlignment.START は、子コントロールをページの上部に配置します。
プロパティ値はMainAxisAlignment列挙型で、以下の値があります:
START (default)
END
CENTER
SPACE_BETWEEN
SPACE_AROUND
SPACE_EVENLY
viewsナビゲーション履歴を作成するためのビューコントロールのリスト。
リストの最後のビューがページに表示されます。
最初のビューは、ポップアップできない「ルート」ビューです。
webアプリケーションがWebブラウザで実行されているかどうかを示す真偽値。
widthWebページやネイティブOSウィンドウの内容領域の幅を取得できる。このプロパティは読み取り専用で、page.on_resizeハンドラーでよく使われる。
window_always_on_top️デスクトップのみ。ウィンドウが他のウィンドウの上に常に表示されるかどうかを設定する。デフォルトはFalse。
window_bgcolor️デスクトップのみ。アプリケーションウィンドウの背景色を設定する。page.bgcolorと一緒に使って、ウィンドウを透明にすることができる。
window_focused️デスクトップのみ。Fletアプリを含むネイティブOSウィンドウにフォーカスを設定するかどうかを設定する。Trueにすると、ウィンドウがフォアグラウンドに移動する。
window_frameless️デスクトップのみ。アプリウィンドウをフレームレスにするかどうかを設定する。Trueにすると、タイトルバーや境界線がなくなる。
window_fullscreen️デスクトップのみ。アプリのネイティブOSウィンドウをフルスクリーンモードに切り替えるかどうかを設定する。デフォルトはFalse。
window_height️デスクトップのみ。Fletアプリを含むネイティブOSウィンドウの高さを取得または設定する。
window_left️デスクトップのみ。Fletアプリを含むネイティブOSウィンドウの水平位置を取得または設定する。画面の左端からの仮想ピクセル単位の距離である。
window_maximizable️デスクトップのみ。「最大化」ボタンを表示/無効化するかどうかを設定する。デフォルトはTrue。
window_maximized️デスクトップのみ。Fletアプリを含むネイティブOSウィンドウが最大化されているかどうかを示す真偽値。このプロパティをTrueに設定すると、プログラム的にウィンドウを最大化し、Falseに設定すると元に戻すことができる。
window_max_height️デスクトップのみ。Fletアプリを含むネイティブOSウィンドウの最大高さを取得または設定する。
window_max_width️デスクトップのみ。Fletアプリを含むネイティブOSウィンドウの最大幅を取得または設定する。
window_minimizable️デスクトップのみ。「最小化」ボタンを表示/無効化するかどうかを設定する。デフォルトはTrue。
window_minimized️デスクトップのみ。Fletアプリを含むネイティブOSウィンドウが最小化されているかどうかを示す真偽値。このプロパティをTrueに設定すると、プログラム的にウィンドウを最小化し、Falseに設定すると元に戻すことができる。
window_min_height️デスクトップのみ。Fletアプリを含むネイティブOSウィンドウの最小高さを取得または設定する。
window_min_width️デスクトップのみ。Fletアプリを含むネイティブOSウィンドウの最小幅を取得または設定する。
window_movable️デスクトップのみ。macOSのみ。ユーザーがFletアプリを含むネイティブOSウィンドウの位置を変更できるかどうかを設定する。デフォルトはTrue。
window_opacity️デスクトップのみ。ネイティブOSウィンドウの不透明度を設定する。値は0.0(完全に透明)から1.0(完全に不透明)の間でなければならない。
window_resizable️デスクトップのみ。ユーザーがFletアプリを含むネイティブOSウィンドウのサイズを変更できるかどうかを設定する。デフォルトはTrue。
window_title_bar_hidden️デスクトップのみ。タイトルバーを非表示にするかどうかを設定する。WindowDragAreaコントロールを使って、タイトルバーが隠れているときにアプリウィンドウを移動できるようにすることができる。
window_title_bar_buttons_hidden️デスクトップのみ。タイトルバーが隠れているときに、ウィンドウ操作ボタンを非表示にするかどうかを設定する。macOSのみ。
window_top️デスクトップのみ。Fletアプリを含むネイティブOSウィンドウの垂直位置を取得または設定する。画面の上端からの仮想ピクセル単位の距離である。
window_prevent_close️デスクトップのみ。「閉じる」シグナルをインターセプトするかどうかを設定する。page.on_window_event (close) イベントハンドラーと page.window_destroy () を使って、アプリ終了確認ロジックを実装できる - page.window_destroy () のコード例を参照してください。
window_progress_value️デスクトップのみ。タスクバー(Windows)やDock(macOS)のアプリケーションボタンにプログレスバーを表示するための0.0から1.0までの値。
window_skip_task_bar️デスクトップのみ。タスクバー(Windows)やDock(macOS)からアプリケーションを隠すかどうかを設定する。
window_visibleデスクトップのみ。Trueに設定すると、アプリケーション・ウィンドウが表示されます。アプリが非表示のウィンドウで起動している場合に使用します。
window_widthデスクトップのみ。Fletアプリを含むネイティブOSウィンドウの幅を取得または設定します。

view

✅最上位のコントロール

すべてのコントロール(テキスト、ボタンなど)はviewの中に配置していくイメージ。

アプリを起動すると自動的にviewが1つ生成される。

💡
複数のviewで画面遷移も作れる!

viewのプロパティ一覧
💡
この表は公式ドキュメントを翻訳してまとめたものです。不明な点があれば公式ドキュメントをご確認ください。

https://flet.dev/docs/controls/view

プロパティ名概要
appbarページの上部に表示するAppBarコントロールを指定する。
auto_scroll子要素が更新されたときにスクロールバーの位置を自動的に移動するかどうかを指定する。Falseにすると、scroll_to()メソッドが使える。
bgcolorページの背景色を指定する。色の値は16進数やflet.colorsモジュールの名前で指定できる。
controlsページに表示するControlのリストを指定する。page.controls.append()やpage.add()で追加できる。
fullscreen_dialogこのビューがフルスクリーンダイアログかどうかを示す真偽値。MaterialとCupertinoでは、フルスクリーンであるということは、アプリバーに戻るボタンではなく閉じるボタンが表示されることを意味する。iOSでは、ダイアログの遷移は異なってアニメーションし、またバックスワイプジェスチャーで閉じることができない。
routeビューのルート - Fletでは使用されていませんが、ビューがポップしたときにpage.routeを更新するためにユーザープログラムで使用することができます。
floating_action_buttonページの内容の上に表示するFloatingActionButtonコントロールを指定する。
horizontal_alignment子要素を水平方向にどのように配置するかを指定する。デフォルト値はCrossAxisAlignment.STARTで、ページの左側に配置されることを意味する。プロパティ値はCrossAxisAlignment列挙型で、以下の値がある:
START (default)
CENTER
END
STRETCH
BASELINE
on_scroll_intervalon_scrollイベントの間引き時間(ミリ秒)を指定する。デフォルトは10.
paddingページの内容とその端との間隔を指定する。デフォルト値は各辺から10ピクセルである。ゼロパディングに設定するには:page.padding = 0. 詳細と可能な値については、Container.paddingを参照してください。
scrollコンテンツのオーバーフローを防ぐために、ページの垂直スクロールを有効にします。
プロパティ値はオプションの ScrollMode 列挙型で、デフォルトは None です。
サポートされる値:
None (デフォルト) - 行はスクロール不可能で、コンテンツがオーバーフローする可能性があります。
AUTO - スクロールが有効で、スクロールが発生したときにのみスクロール バーが表示されます。
ADAPTIVE - ウェブまたはデスクトップとしてアプリを実行している場合、スクロールが有効になり、スクロールバーが常に表示されます。
ALWAYS - スクロールが有効で、スクロールバーが常に表示されます。
HIDDEN - スクロールは有効ですが、スクロールバーは常に非表示です。
spacingページ上のコントロール間の垂直方向の間隔を指定します。デフォルト値は10ピクセルです。間隔は、alignmentがstart, end, centerの場合にのみ適用されます。
vertical_alignment子要素を垂直方向にどのように配置するかを指定する。デフォルト値はMainAxisAlignment.STARTで、ページの上部に配置されることを意味する。プロパティ値はMainAxisAlignment列挙型で、以下の値がある:
START (default)
END
CENTER
SPACE_BETWEEN
SPACE_AROUND
SPACE_EVENLY

カウンターアプリの場合

1つのviewの中にRowが配置されているシンプルな構成。

(viewはpageによって管理されているが、今回はあまり意識する必要はない。)

Image in a image block

内部的にはWebアプリとして動作している

✅ネイティブOSのウィンドウで起動していても、内蔵のWebサーバーがバックグラウンドで起動している。

Image in a image block

画面の作り方

コントロールを画面に追加する方法

✅コントロールを画面に追加するには、「コントロールの追加」と「画面への反映」が必要。

💡
2種類の書き方がある。

【パターン1】追加してから反映するappend, update

appendでコントロールを追加して、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)

【パターン2】追加と反映をまとめて行うadd

addを使えばappendupdateをまとめて実行できる。

import flet as ft

def main(page: ft.Page):
    t = ft.Text(value="Hello, world!", color="green")
		# テキストを追加、画面に反映
    page.add(t)

ft.app(target=main)

💡
基本はaddでOK!

カウンターアプリの場合

コントロール「Row」を画面に追加している。

import flet as ft

def main(page: ft.Page):
    page.title = "Flet counter example"
    page.vertical_alignment = ft.MainAxisAlignment.CENTER

    txt_number = ft.TextField(value="0", text_align=ft.TextAlign.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()

		# ✅ここでコントロールRowを画面に追加している!
    page.add(
				# Rowを画面に追加
        ft.Row(
            [
								# 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(target=main)
Image in a image block

コントロールの更新

✅すでに画面にあるコントロールの値(プロパティ)を更新するにはpage.update()を実行する。

txt = ft.TextField(value="あいうえお")
page.add(t)

# ✅すでに画面にあるtxtコントロールの値を更新する
txt.value = "かきくけこ"
page.update()

💡
画面を更新するにはupdateが必要!

カウンターアプリの場合

カウンターの値を更新するためにpage.update()を使用している。

import flet as ft

def main(page: ft.Page):
    page.title = "Flet counter example"
    page.vertical_alignment = ft.MainAxisAlignment.CENTER

    txt_number = ft.TextField(value="0", text_align=ft.TextAlign.RIGHT, width=100)

		# マイナスボタンをクリック
    def minus_click(e):
				# ✅値を-1して更新
        txt_number.value = str(int(txt_number.value) - 1)
        page.update()

		# プラスボタンをクリック
    def plus_click(e):
				# ✅値を+1して更新
        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(target=main)

コントロールの削除

popメソッドで削除できる。

例:一番上のコントロールを削除する

# 削除
page.controls.pop()
# 画面を更新
page.update()

カウンターアプリの場合

例として、プラスボタンを押したとき、プラスボタンを削除するようにしてみる。

Image in a image block
import flet as ft

def main(page: ft.Page):
    page.title = "Flet counter example"
    page.vertical_alignment = ft.MainAxisAlignment.CENTER

    txt_number = ft.TextField(value="0", text_align=ft.TextAlign.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.controls[0].controls.pop(2) # controls[0]はRowのこと
																				 # →controls[0].controlsにはマイナスボタン、テキストフィールド、プラスボタンの3つが入っている
																				 # →→controls[0].controls.pop(2)はプラスボタンの削除を意味する
        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(target=main)

コントロールの種類
お手軽にそれっぽい画面を作る

✅画面を作るためのテンプレートが公式サイトにたくさん載っている。

公式のテンプレート:https://flet-controls-gallery.fly.dev/layout

コピペすれば使えるので、簡単にモダンな画面が作れる😊

例えばタブを作りたいときは……

Image in a image block
Image in a image block
Image in a image block

💡
これをペーストするだけでいい感じものができそう!

画面を制御するためのプロパティ

画面を制御するために、コントロールにはさまざまなプロパティが用意されている。

イベントハンドラーon_〇〇

on_〇〇 = 任意の処理でイベントハンドラーを設定できる。

💡
「クリックしたとき✗✗する」みたいなやつ

ここでは代表的なイベントハンドラーon_〇〇を3つ紹介する!

クリックイベントon_click

例:ボタンをクリックしたら「Click me」と表示する。

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

# ✅クリックしたときbutton_clickedを実行する
page.add(ft.ElevatedButton(text="Click me", on_click=button_clicked))

Image in a image block


チェンジイベントon_change

例:チェックを付け外ししたとき「True」「Flase」の表示が切り替わる。

output_text = ft.Text()
def checkbox_changed(e):
    output_text.value = (
        f"チェックボックスの値 :  {todo_check.value}."
    )
    page.update()

# ✅チェックを付け外ししたときcheckbox_changedを実行する
todo_check = ft.Checkbox(label="テスト", value=False, on_change=checkbox_changed)
page.add(todo_check, output_text)

Image in a image block


ページ遷移イベントon_route_change

例:ページ遷移するとき目的のページ(テストページ)に遷移するよう設定する。

※ページ遷移の仕組みは後で解説する。

import flet
from flet import ElevatedButton, Page, Text, View


def main(page: Page):
    # ページ遷移イベント
    def route_change(e):
        print("Route change:", e.route)
        
        # ページクリア
        page.views.clear()

        # トップページ
        page.views.append(
            View(
                "/",
                [
                    ElevatedButton("テストページへ移動", on_click=open_test),
                ],
            )
        )
        # テストページ
        if page.route == "/test":
            page.views.append(
                View(
                    "/test",
                    [
                        Text("これはテストページです"),
                    ],
                )
            )
            
        # ページ更新
        page.update()

    # ✅ページ遷移イベントの登録
    page.on_route_change = route_change

    # テストページへ移動
    def open_test(e):
        page.go("/test")

    page.go(page.route)


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

Image in a image block


その他のイベント

公式ドキュメントの各コントロールの「events」の説明を参照。

例:ElevatedButtonのイベントハンドラーの一覧

Image in a image block


カウンターアプリの場合

「マイナスボタン」と「プラスボタン」にクリックイベントon_clickを設定している。

import flet as ft

def main(page: ft.Page):
    page.title = "Flet counter example"
    page.vertical_alignment = ft.MainAxisAlignment.CENTER

    txt_number = ft.TextField(value="0", text_align=ft.TextAlign.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(
            [
								# ✅クリックしたとき「minus_click」を実行する
                ft.IconButton(ft.icons.REMOVE, on_click=minus_click),
                txt_number,
								# ✅クリックしたとき「plus_click」を実行する
                ft.IconButton(ft.icons.ADD, on_click=plus_click),
            ],
            alignment=ft.MainAxisAlignment.CENTER,
        )
    )

ft.app(target=main)

コントロールの表示/非表示visible

visible = Falseでコントロールが見えなくなる。

すべてのコントロールに表示/非表示の設定ができる。

# テキスト非表示(visible=False)
t = ft.Text(value="Hello, world!", color="green", visible=False)
page.add(t)

非表示にしたときの挙動
  • 画面に表示されない
  • フォーカスできない
  • 選択できない
  • イベントが発生しない
  • 上記すべて、子要素にも適用される

コントロールの有効/無効disabled

disabled = Trueでコントロールが触れなくなる。

Image in a image block

すべてのコントロールに有効/無効の設定ができる。

# チェックボックス有効
check01 = ft.Checkbox( label="有効なチェックボックス", value=False )
page.add(check01)

# チェックボックス無効(disabled=True)
check02 = ft.Checkbox( label="無効なチェックボックス", value=False, disabled=True )
page.add(check02)

無効にしたときの挙動
  • フォーカスできない
  • 選択できない
  • イベントが発生しない
  • 上記すべて、子要素には適用されない

コントロールに任意の値を格納data

dataプロパティは自由にデータを格納してOK

💡
すべてのコントロールにdataプロパティを設定できる。
汎用性が高くて便利!

data動作には影響しないので、何か値を残したいときはここに入れておくといい。

# テキストを生成
txt = ft.Text(value="Hello, world!")

# 任意の値を持たせておくことができる
txt.data = "hoge"

Image in a image block

画面遷移

⚠️
個人的に一番理解に時間がかかった

例:

トップページ

→ テストページ

→ トップページへ戻る

Image in a image block

💡
この例を実現する方法を解説する!

最終的なソースコード

hoge.py(任意のファイル名でOK)の1ファイルだけで作れる!

画面ごとにファイルを作るわけではない!

import flet
from flet import AppBar, ElevatedButton, Page, Text, View


def main(page: Page):
    # ---------------------------------
    # 関数定義
    # ---------------------------------
    # ページを更新する
    def route_change(e):
        print("Route change:", e.route)
        
        # ページクリア
        page.views.clear()

        # トップページ(常にviewに追加する)
        page.views.append(
            View(
                "/",
                [
                    AppBar(title=Text("トップページ")),
                    ElevatedButton("テストページへ移動", on_click=open_test),
                ],
            )
        )
        # テストページ(テストページのときだけviewに追加する)
        if page.route == "/test":
            page.views.append(
                View(
                    "/test",
                    [
                        AppBar(title=Text("テストページ")),
                        Text("これはテストページです"),
                    ],
                )
            )
            
        # ページ更新
        page.update()

    # 現在のページを削除して、前のページに戻る
    def view_pop(e):
        print("View pop:", e.view)
        page.views.pop()
        top_view = page.views[-1]
        page.go(top_view.route)

    # テストページへ移動
    def open_test(e):
        page.go("/test")


    # ---------------------------------
    # イベントの登録
    # ---------------------------------
    # ページ遷移イベントが発生したら、ページを更新
    page.on_route_change = route_change
    # AppBarの戻るボタンクリック時、前のページへ戻る
    page.on_view_pop = view_pop


    # ---------------------------------
    # 起動時の処理
    # ---------------------------------
    # ページ遷移を実行
    page.go(page.route)


flet.app(target=main)

前提
  • 複数のviewを使って画面遷移を実現する。
  • 複数viewがあるときは、末尾のviewが画面に表示される。
  • viewは変数pageによって管理されている。

ページのクリア
  # ページクリア
  page.views.clear()

  • ページ遷移したら毎回viewをクリアする。
  • その後空っぽになったviewに、必要なviewを追加する(この後の説明を参照)


トップページ
# トップページ(常にviewに追加する)
page.views.append(
    View(
        "/",
        [
            AppBar(title=Text("トップページ")),
            ElevatedButton("テストページへ移動", on_click=open_test),
        ],
    )
)

  • viewが1つあるだけのシンプルな画面。
Image in a image block


テストページ
# トップページ(常にviewに追加する)
page.views.append(
    View(
        "/",
        [
            AppBar(title=Text("トップページ")),
            ElevatedButton("テストページへ移動", on_click=open_test),
        ],
    )
)

# テストページ(テストページのときだけviewに追加する)
if page.route == "/test":
    page.views.append(
        View(
            "/test",
            [
                AppBar(title=Text("テストページ")),
                Text("これはテストページです"),
            ],
        )
    )

  • viewを2つ持っている。
    • page.views[0] = トップページ(前のページ) 👈これは見えない
    • page.views[1] = テストページ(今のページ) 👈一番末尾の要素が画面上に表示される
  • これによって、AppBarに戻るボタンが表示される。(前の画面が分かる)
Image in a image block


ページ遷移するたびにページをクリア(clear)してから、ページを追加(append)しているのがややこしい

❌「ページ遷移 = 遷移先のページを指定する」

⭕️「ページ遷移 = viewの配列を作る」

💡
これが直感的ではなく、理解に時間がかかった…

公式の解説:https://flet.dev/docs/guides/python/navigation-and-routing

Qiitaの解説:https://qiita.com/usagi_11/items/0ffcd7d209cf8a3733be

Qiitaの解説:https://qiita.com/donraq/items/b0cc1ad273996477b25a

公式サンプルコード:https://github.com/flet-dev/examples/blob/main/python/apps/routing-navigation/building-views-on-route-change.py