0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【備忘録】Fletでモーダル画面を各ボタンで表示できるようにする

Last updated at Posted at 2025-01-15

1.初めに

本記事ではモーダル画面を複数表示するコードについて紹介します。基本ベースは公式ドキュメントから作成し、これをclassに焼き直しました。その際に最も重要なことはclassコンポーネントにPageを渡すことでした。

実行環境

  • Python : 3.13.1
  • Flet : 0.25.2

2.クラスコンポーネント化

公式ドキュメントではmain関数内で

  • AlertDialogを作成(以下、dlg_modalと表現)
  • 作成したdlg_modalは以下の関数で表示/非表示
     * 表示:page.open(dlg_modal)
     * 非表示:page.close(dlg_modal)
  • ElevatedButtonを作成し、クリックイベントにpage.open(dlg_modal)を設定(引数を設定するためラムダ式を使用)
  • main関数内でモーダルを閉じるイベントを定義

といったことをしています。これを、コンポーネント化しました。(モーダルを表示/非表示するイベントを登録したElevatedButtonの自作class)このclassの作成に当たり重要なことはpageをclassの引数に渡すことです。(モーダルの表示/非表示を行うため。)

元ネタはこちらをご参照いただき、クラス化した結果が以下の通りです。

class My_Dialog(ElevatedButton):
    def __init__(self, page: Page, task_id: int, task_name: str):
        super().__init__()
        self.page = page
        self.task_id = task_id
        self.task_name = task_name
        self.text = f'Open modal Dialog {self.task_id}'
        self.dlg_modal = AlertDialog(
            modal=True,
            title=Text(f'Please Confirm #{self.task_id}'),
            content=Text(f'Task : {self.task_name}'),
            actions=[
                ElevatedButton(f'Yes #{self.task_id}', on_click=self.handle_event),
                ElevatedButton(f'No #{self.task_id}', on_click=self.handle_event),
            ],
            actions_alignment=MainAxisAlignment.END,
        )
        self.on_click = lambda e: self.page.open(self.dlg_modal)

    def handle_event(self, e) -> None:
        self.page.close(self.dlg_modal)

(クラスを定義するときに、よく忘れるのがコンストラクタ内のsuper().__init__()ですね。)
上記コンポーネントではモーダルを表示/非表示のみのイベント登録をしていませんが、データ編集やデータ削除機能などを搭載するのが想定される用途です。

3.作成物

コンポーネント化されたコードを用いた例を以下に記載します。

import flet as ft
from flet import (
    AlertDialog,
    Column,
    CrossAxisAlignment,
    ElevatedButton,
    MainAxisAlignment,
    Page,
    Text,
)

# テストデータ
tasks = [
    {'id': 1, 'task_name': 'Sample1'},
    {'id': 2, 'task_name': 'Sample2'},
    {'id': 3, 'task_name': 'Sample3'},
    {'id': 4, 'task_name': 'Sample4'},
    {'id': 5, 'task_name': 'Sample5'},
    {'id': 6, 'task_name': 'Sample6'},
    {'id': 7, 'task_name': 'Sample7'},
    {'id': 8, 'task_name': 'Sample8'},
]


class My_Dialog(ElevatedButton):
    def __init__(self, page: Page, task_id: int, task_name: str):
        super().__init__()
        self.page = page
        self.task_id = task_id
        self.task_name = task_name
        self.text = f'Open modal Dialog {self.task_id}'
        self.dlg_modal = AlertDialog(
            modal=True,
            title=Text(f'Please Confirm #{self.task_id}'),
            content=Text(f'Task : {self.task_name}'),
            actions=[
                ElevatedButton(f'Yes #{self.task_id}', on_click=self.handle_event),
                ElevatedButton(f'No #{self.task_id}', on_click=self.handle_event),
            ],
            actions_alignment=MainAxisAlignment.END,
        )
        self.on_click = lambda e: self.page.open(self.dlg_modal)

    def handle_event(self, e) -> None:
        self.page.close(self.dlg_modal)


def main(page: Page):
    page.title = 'My Dialogs'
    page.window.width = 600
    page.horizontal_alignment = CrossAxisAlignment.CENTER
    # モーダル設定済みのボタンを縦に並べる
    modal_btns = Column()
    for task in tasks:
        tmp_modal = My_Dialog(page, task.get('id'), task.get('task_name'))
        modal_btns.controls.append(tmp_modal)
    page.add(modal_btns)


ft.app(target=main)

上記コードを実行し、ボタンを押下すると以下のようにモーダル画面が表示されます。(2個目のボタンを押下しています。)

スクリーンショット 2025-01-15 222923.png

最後に

比較的簡単にモーダルを表示させることができました。
試してはいませんが、モーダル画面の中でさらにモーダル画面の表示なんかできるのでしょうかね?(機会があれば試してみようと思います。)

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?