🐍

[Flet入門] 主要コントロールの使い方

2023/07/19に公開

はじめに

https://zenn.dev/gogotealove/articles/3cb92bcdfac15f

Python でクロスプラットフォーム GUI アプリを作るのであれば最近のイチオシは flet です。イマドキな UI と敷居の低さが最高です。

コントロールの紹介

https://flet.dev/docs/controls/
https://flet-controls-gallery.fly.dev/layout

迷ったら公式リファレンスとコントロールギャラリーまで。特にギャラリーはおすすめです。全ての動作イメージ確認とソースコードが閲覧できます。これをコピペしているだけで何でも作れちゃう感。

共通プロパティ

名称 説明 デフォルト値
data 汎用的なデータを格納できます。ともかく便利。 None
disabled コントロールを無効化します。TextField をはじめとした各種コントロールで有効。親子関係がある場合は、子まで伝播します。 False
visible 視覚的な表示 / 非表示。非表示コントロールからはイベントも発火しません。 True
opacity 0.0(不透明)~1.0(透明)までの透明度。 0
top / bottom / left / right Stack を使った時にコントロールをレイヤーする位置調整用。 0

全てのコントロールに共通して備わっているプロパティのうち、よく使うものをピックアップしました。ともかく data が便利です。

Page

アプリケーションウィンドウそのものに対する様々な設定は Page と呼ばれる最上位のコントロールにまとめられています。

import flet as ft


def main(page: ft.Page):
    page.title = "My First App"  # タイトル

    page.window_width = 300  # 幅
    page.window_height = 300  # 高さ
    page.window_minimizable = False  # 最小化ボタン
    page.window_maximizable = False  # 最大化ボタン
    page.window_resizable = False  # ウィンドウサイズ変更可否

    page.bgcolor = ft.colors.ORANGE  # ウィンドウ背景色
    page.window_opacity = 0.8  # ウィンドウ透過(0.0 ~ 1.0)

    page.update()  # プロパティ変更した場合は update()


ft.app(target=main)

よく触りそうなのは上記のあたりかなと思います。

import flet as ft


def main(page: ft.Page):
    page.title = "My First App"  # タイトル

    page.window_width = 300  # 幅
    page.window_height = 300  # 高さ
    page.window_top = 100  # 位置(TOP)
    page.window_left = 100  # 位置(LEFT)
    page.window_always_on_top = True  # ウィンドウを最前面に固定

    page.update()  # プロパティ変更した場合は update()

    # page.window_center()  # ウィンドウをデスクトップの中心に移動


ft.app(target=main)

他にもウィンドウの位置については上記のようなプロパティ/メソッドがありますが、大体は想像の通りの動きをするので戸惑うことはないかと。

Text

文字列です。ラベルと呼ばれたりすることもありますが、flet では Text と呼びます。これを直接 Page に張り付けて使うケースは意外と少ないのですが、主要コントロールのキャプションにこのオブジェクトを渡すことが多いですし、プロパティ値のモニタリングデバッグで使ったりしますので基本ということで紹介します。

import flet as ft


def main(page: ft.Page):
    t1 = ft.Text("標準の文字")
    t2 = ft.Text(
        "大きく太い赤い文字",
        size=50,  # サイズ(default:14)
        weight=ft.FontWeight.W_900,  # 太さ(default:NORMAL)
        color=ft.colors.RED,  # 色
        selectable=True,  # 選択可否(default:False)
    )

    page.add(t1, t2)


ft.app(target=main)

文字をゴテゴテと装飾したりする機会は少ないと思います。サイズ、色くらいでしょうか。

イベントハンドラ

import flet as ft


def main(page: ft.Page):
    def button_clicked(e):
        t1.data += 1
        t2.value = f"{t1.data} times clicked!"
        t2.update()

    t1 = ft.Text(
        spans=[
            ft.TextSpan(
                "わたしをクリックして",
                on_click=button_clicked,  # TextSpan の on_click イベントで発火
            ),
        ],
        data=0,  # クリックカウンタをここに持たせておく
    )
    t2 = ft.Text()

    page.add(t1, t2)


ft.app(target=main)

on_click などを拾いたい場合は TextSpan オブジェクトを介する必要があります。 spans プロパティに TextSpan を放り込んで、そこから発火させてください。

なんでこんな仕様なのか分からないですが、Text のイベント拾いたいケースがあまりないので気にしない事にします。

Buttons

いくつか種類ありますのでお好みでどうぞ。

イベントハンドラ

import flet as ft


def main(page: ft.Page):
    def button_clicked(e):
        t2.value = "recomended!"
        t2.update()

    b1 = ft.FilledTonalButton(
        text="わたしを推してください",
        icon=ft.icons.RECOMMEND,
        on_click=button_clicked,
    )
    t2 = ft.Text()

    page.add(b1, t2)


ft.app(target=main)

イベント名 発火条件
on_click ボタン押下時
on_hover カーソル通過時
on_long_press ボタン長押し時

特段迷うポイントはないと思います。このコントロールに限らずですが、Material Icons が使えるのは便利ですね。

Discussion