werry-chanの日記.料理とエンジニアリング

料理!コーディング!研究!日常!飯!うんち!睡眠!人間の全て!

FletのCheckBoxに値を保持させてon_changeイベントでvalue参照&複数引数も実装

Flutter baseのpythonクロスプラットフォームGUIライブラリのFLET
まだまだ開発途上なのか工夫しないと複雑な実装は難しいです。

例えばcheckboxに値を持たせても, on_changeイベントからは, どのcheckboxが押されているのか参照不能な状態です。
checkbox以外のオブジェクトについても同様の問題があります。

今回はcheckboxを例に, オブジェクトの値を保持し, イベント発火されたオブジェクトを特定してみましょう。
さらに今回は, イベント発火時に複数引数を持たせる部分まで実装して使い勝手を良くしていきます。

まずは自分の値を参照可能な自作クラスを公式参考に作っていきます。
公式よりUser controls | Flet

import flet as ft

class my_CheckBox(ft.UserControl):
    def __init__(self, label, value:bool = False):
        super().__init__()
        self.label = label
        self.value = value 
    def build(self):
        # イベント関数はbuild直下に書かないと動かない
        def on_change(e, message: str):
            # 自作checkboxはイベント発火後に自前実装で値の変更必要
            self.value = not(self.value)
            print(self.label, 'is changed!!', 'value:', self.value)
            print('message', message, end='\n\n')
            self.update()
        return ft.Checkbox(label=self.label,
                           value=self.value,
                           on_change=(lambda e: on_change(e, message=self.label)))
       # lamda式を使ってイベント発火に複数引数を持たせる

ほぼほぼ完成です。
あとはこいつをmainに載せて実験するだけです。

とりあえずListViewで100個くらいcheckbox作って適当に押してみます。

import flet as ft

class my_CheckBox(ft.UserControl):
    def __init__(self, label, value:bool = False):
        super().__init__()
        self.label = label
        self.value = value 
    def build(self):
        # イベント関数はbuld直下に書かないと動かない
        def on_change(e, message: str):
            # 自作checkboxはイベント発火後に自前実装で値の変更必要
            self.value = not(self.value)
            print(self.label, 'is changed!!', 'value:', self.value)
            print('message', message, end='\n\n')
            self.update()
        return ft.Checkbox(label=self.label,
                           value=self.value,
                           on_change=(lambda e: on_change(e, message=self.label)))
       # lamda式を使ってイベント発火に複数引数を持たせる

def main(page):
    lv = ft.ListView(expand=1, spacing=10, padding=20)

    for i in range(100):
        lv.controls.append(my_CheckBox('my_CheckBox' + str(i)))
    page.add(lv)

ft.app(target=main)
生成された初期画面
my_CheckBox1を押してみる

これできちんと実装できていればterminalに以下のような表示が出てきます。

my_CheckBox1 is changed!! value: True
message my_CheckBox1
次はmy_CheckBox3を押してみる
my_CheckBox1 is changed!! value: True
message my_CheckBox1

my_CheckBox3 is changed!! value: True
message my_CheckBox3

他の番号を押したらきちんと表示が変わりましたね。

次は, checkboxのbool値がきちんと変更されるか試してみます。

my_CheckBox3のチェックを外してみる
my_CheckBox1 is changed!! value: True
message my_CheckBox1

my_CheckBox3 is changed!! value: True
message my_CheckBox3

my_CheckBox3 is changed!! value: False
message my_CheckBox3

ちゃんとチェック外れたことを認識できていますね。

複数引数のmessage部分にも正しい値が渡されていることが見て取れます。


FletはPythonだけでクロスプラットフォームGUI実装できるので便利です。
しかしながら, 新しい道具使うときには不具合が発生しがちなので, 大切な実装を進める際にはある程度枯れた知見のある道具が安全です。
普通にFlutterとかReact使うのが安全ってことです。pythonと連携させるのが怠いのが難点ですが。


追伸
坂道だらけ地域に住んでて車持つにも微妙な都内住みだったので, 電動自転車買ったら最高でした。
なんで税金かからないのか分からない。1カ月くらい充電保つ, 70km走れるとか。
BE-FD631B ビビ・DX 26型(オニキスブラック)|ビビ・DX【パナソニック公式通販】