【Flet】GridViewの内容を中央揃えで表示したい【Python】
やりたいこと
Fletには複数のコントロールをいい感じに一覧表示してくれるGridViewコントロールが存在します。
このGridViewがどのような働きをするのかは、公式のアイコンブラウザーを見ればだいたい分かると思います。このGridView、表示するコントロールの数が少ないときには左上にすべてが寄るかたちになって少し寂しい見た目になってしまいます。(GridViewの使用場面を考えれば当然ですが)
これを以下のように中央に寄せて表示したい場面があったのですが、一筋縄ではいかなかったのでその方法を記しておきます。
結論
GridViewをContainerの中に入れ、Containerの内容を中央揃えにするようにします。
そして、GridViewの幅(width
プロパティ)をそのmax_extent
プロパティとcontrols
プロパティ(これはリスト型)の長さを掛けた値に設定すれば解決です。
ソースコード
import flet as ft
def main(page: ft.page):
gv = ft.GridView(
spacing=30,
run_spacing=30,
max_extent=200,
)
ct = ft.Container(
content=gv, # GridViewを内包
alignment=ft.alignment.center, # Containerの内部を中央寄せ
expand=1, # expandを1に設定することでGridViewがスクロールできるようになる
)
for i in range(3):
gv.controls.append(
ft.Container(
bgcolor=ft.colors.BLUE,
border_radius=20,
)
)
# GridViewの幅をmax_extent × controlsの長さに設定
gv.width = gv.max_extent * len(gv.controls)
page.add(ct)
ft.app(main)
実行結果
原理
なんで上記のようなコードにする必要があるのか、自分で気づくのに紆余曲折あったのでそれを記していこうと思います。
まず、これから解説する内容の元となるコードを紹介しておきます。
import flet as ft
def main(page: ft.page):
gv = ft.GridView(
spacing=30,
run_spacing=30,
max_extent=200,
)
for i in range(3):
gv.controls.append(
ft.Container(
bgcolor=ft.colors.BLUE,
border_radius=20,
)
)
page.add(gv)
ft.app(main)
GridViewに青色のContainerを3つだけ入れた単純なコードです。
max_extent
を設定しておくことで、ウィンドウサイズを変更してもいい感じにGridViewが内包するコントロールの大きさを調整してくれるようになります。(今回はこのmax_exnten
ありきで書いていきます)
GridViewに中央寄せをするプロパティはない
公式ドキュメントを読んだり、ChatGPTやGeminiに聞いてみたりしたのですが、FletのGridViewコントロールにはalignment
のような整列方法を設定するプロパティは存在しないようです。
そのため、今回のようにGridViewで中央寄せを実現したい場合は別のアプローチを考えなければいけません。
alignment
を設定
Containerに入れてGridView単体では中央寄せをできないのであれば、親要素で中央に寄せてやろう!ということで以下のようなコードを書いてみました。
import flet as ft
def main(page: ft.page):
gv = ft.GridView(
spacing=30,
run_spacing=30,
max_extent=200,
)
ct = ft.Container(
content=gv, # GridViewを内包
alignment=ft.alignment.center, # Containerの内部を中央寄せ
)
for i in range(3):
gv.controls.append(
ft.Container(
bgcolor=ft.colors.BLUE,
border_radius=20,
)
)
page.add(ct)
ft.app(main)
魂胆は単純で、GridViewをContainerに入れて、Container内部のレイアウトを中央寄せに設定しただけです。
これで解決!と思ったのですが実行してみるとあらびっくり
Containerに内包しないときと何も変わっていません。
なんで??
GridViewは横に延びる
どうやら、GridViewは親要素の領域の許す限り無制限に横方向にスペースを占拠する仕様のようです。(上下方向には不必要に延びない)
たとえば、内包する要素が3つだけの以下のようなGridViewでも、GridViewの占めるスペースは以下のようになっています。
そのため、親要素のContainerで中央寄せに設定しても場所が動かない、という状況に陥っていました。
GridViewの幅を設定する
これを解決するには、GridViewの領域を以下のように表示するコントロールにフィットさせる必要があります。
GridViewコントロールにはwidth
プロパティが用意されているので、これを適切な値に設定することができれば、問題を解決できそうです。
今回使用しているコードでは、最大幅200(max_extent=200
)のContainerが3つ並ぶというGridViewになっています。そのため、600をGridViewの幅として設定してあげればちょうど良さそうです。
ここで、冒頭の結論で述べた
gv.width = gv.max_extent * len(gv.controls)
という計算式が出てきます。
GridViewのcontrols
にコントロールを追加し終わったタイミングでこの計算式を実行するとGridViewの幅が希望通りに調整され、狙ったようにGridViewを中央揃えにできます!
完成形コード
import flet as ft
def main(page: ft.page):
gv = ft.GridView(
spacing=30,
run_spacing=30,
max_extent=200,
)
ct = ft.Container(
content=gv, # GridViewを内包
alignment=ft.alignment.center, # Containerの内部を中央寄せ
expand=1, # expandを1に設定することでGridViewがスクロールできるようになる
)
for i in range(3):
gv.controls.append(
ft.Container(
bgcolor=ft.colors.BLUE,
border_radius=20,
)
)
# GridViewの幅をmax_extent × controlsの長さに設定
gv.width = gv.max_extent * len(gv.controls)
page.add(ct)
ft.app(main)
おまけ
結論でさらっとコメントアウトしてましたが、GridViewの親要素となるContainerのexpand
プロパティを1
(またはTrue
)に設定しておくと、GridViewがウィンドウをはみ出るほど下方向に延びてもスクロールができるようになります。
#~~~省略~~~#
ct = ft.Container(
content=gv,
alignment=ft.alignment.center,
expand=1, # expandを1に設定することでGridViewがスクロールできるようになる
)
#~~~省略~~~#
Fletはまだベータ版のライブラリということもあり情報も少ないので、すこし難しいことをしようとすると自力で工夫しなければいけいないことが多いですよね(それがFletの楽しいところでもありますが)。
この記事が少しでもあなたの役に立てば幸いです。
Discussion