1.はじめに
本記事はFletで提供されているUI
GridView
ListView
を交互に切り替えるSwitch
を実装したのでその備忘録です。
(※表示したいリストの数が5000件ぐらいなどの場合は分割して表示、無限リロードのような実装を行う必要があります。単純に読み込みが遅くなるので。)
実行環境は
- Python : 3.13.1
- Flet : 0.25.2
2.コンポーネントの説明
class My_View(Column):
def __init__(self, view_items: list):
super().__init__()
self.view_items = view_items
# 初期表示はグリッドビューとしています
self.my_switch = Switch(
label='Grid View',
label_style=TextStyle(letter_spacing=0.5, size=16,),
value=True,
on_change=self.switch_changed,
height=25,
active_track_color=Colors.LIGHT_BLUE,
inactive_track_color=Colors.DEEP_ORANGE,
thumb_icon=ControlState.SELECTED,
)
self.my_grid = GridView(
expand=True,
max_extent=200,
child_aspect_ratio=1.0,
)
self.my_list = ListView(
expand=True,
spacing=10,
visible=False,
)
self.controls = [
self.my_switch,
self.my_grid,
self.my_list,
]
def before_update(self):
# コンポーネントの更新が行われる前に、毎回以下のコードが実行される。
# 無限リロードを実装する場合は、ビューのロードと表示の切り替えはそれぞれ別関数で実装する必要あり。
self.my_grid.controls.clear()
self.my_list.controls.clear()
for item in self.view_items:
self.__my_container = Container(
content=Text(item, color=Colors.BLACK, no_wrap=False),
alignment=alignment.center,
bgcolor=Colors.AMBER_100,
border=border.all(1, Colors.AMBER_400),
border_radius=border_radius.all(10),
padding=padding.all(10),
)
if self.my_switch.value:
self.my_grid.visible = True
self.my_list.visible = False
self.my_grid.controls.append(self.__my_container)
else:
self.my_grid.visible = False
self.my_list.visible = True
self.my_list.controls.append(self.__my_container)
def switch_changed(self, e):
self.my_switch.label = 'Grid View' if e.control.value else 'List View'
self.update()
上記実装のポイント:
-
GridView
、ListView
自体はともにcontrols
に追加している(アイテムが空の状態) - 表示しないViewについては
visible=False
とする - Viewに追加している
Container
は共通のものを使用しているが、別個で実装も可能 -
Switch
ボタンをクリックしたときのイベントはvalue=True/False
とlabel
の切り替え、Viewの更新 -
before_update
に記載されたコードは更新が走るたびに、実行される(現実装ではView内に追加されたアイテムは毎回クリアしてから、SwitchのオンオフでViewにアイテムを追加している。)
3.作成物
今回作成したコードをテストデータとともに表示させるコードが以下:
import flet as ft
from flet import (
alignment,
border,
border_radius,
Column,
Colors,
Container,
ControlState,
GridView,
ListView,
padding,
Page,
ScrollMode,
Switch,
Text,
TextStyle,
)
class My_View(Column):
def __init__(self, view_items: list):
super().__init__()
self.view_items = view_items
# 初期表示はグリッドビューとしています
self.my_switch = Switch(
label='Grid View',
label_style=TextStyle(letter_spacing=0.5, size=16,),
value=True,
on_change=self.switch_changed,
height=25,
active_track_color=Colors.LIGHT_BLUE,
inactive_track_color=Colors.DEEP_ORANGE,
thumb_icon=ControlState.SELECTED,
)
self.my_grid = GridView(
expand=True,
max_extent=200,
child_aspect_ratio=1.0,
)
self.my_list = ListView(
expand=True,
spacing=10,
visible=False,
)
self.controls = [
self.my_switch,
self.my_grid,
self.my_list,
]
def before_update(self):
# コンポーネントの更新が行われる前に、毎回以下のコードが実行される。
# 無限リロードを実装する場合は、ビューのロードと表示の切り替えはそれぞれ別関数で実装する必要あり。
self.my_grid.controls.clear()
self.my_list.controls.clear()
for item in self.view_items:
self.__my_container = Container(
content=Text(item, color=Colors.BLACK, no_wrap=False),
alignment=alignment.center,
bgcolor=Colors.AMBER_100,
border=border.all(1, Colors.AMBER_400),
border_radius=border_radius.all(10),
padding=padding.all(10),
)
if self.my_switch.value:
self.my_grid.visible = True
self.my_list.visible = False
self.my_grid.controls.append(self.__my_container)
else:
self.my_grid.visible = False
self.my_list.visible = True
self.my_list.controls.append(self.__my_container)
def switch_changed(self, e):
self.my_switch.label = 'Grid View' if e.control.value else 'List View'
self.update()
def main(page: Page):
# アプリケーション上でスクロールができるように設定
page.scroll = ScrollMode.ADAPTIVE
# テストデータ
my_items = [f'item {i}' for i in range(101)]
# コンポーネントをページに追加
page.add(My_View(my_items))
ft.app(main)
上記コードを実行すると、以下のようなグリッド表示とリスト表示となります。
4.最後に
少々課題が残っていますが、よくあるグリッドからリスト(またはその逆)への表示切替を実装することができました。(件数が膨大な場合は200件ずつなどの塊ごとに表示させるなど工夫の余地あり。)