fletの画面遷移
pythonのGUI超新星(?)であるfletのappbarを利用した画面遷移を備忘録として残します。
めちゃくちゃわかりにくい
公式でもルーティングの例とか挙げてくれてるんやけども、なんせ分かりづらい。
わかりにくい例
def route_change(route):
page.views.clear()
page.views.append(
View(
"/",
[
AppBar(title=Text("index")),
ElevatedButton("Visit Doutonbori", on_click=lambda _: page.go("/doutonbori")),
],
)
)
if page.route == "/doutonbori" or page.route == "/doutonbori/takoyaki":
page.views.append(
View(
"/doutonbori",
[
AppBar(title=Text("Doutonbori")),
ElevatedButton("Search Takoyaki", on_click=lambda _: page.go("/doutonbori/takoyaki")),
],
)
)
if page.route == "/doutonbori/takoyaki":
page.views.append(
View(
"/doutonbori/takoyaki",
[
AppBar(title=Text("Takoyaki")),
Text("たこ焼き食べたい"),
],
)
)
page.update()
def view_pop(view):
page.views.pop()
top_view = page.views[-1]
page.go(top_view.route)
page.on_route_change = route_change
page.on_view_pop = view_pop
page.go(page.route)
ちょっと分かり難く(やばさを分かりやすく)してみた
page.go(page.route)
でroute_change
を呼んでるわけですけど、
page.views.clear()
で全部消してから指定されたルートまで再構築してるんですよね。
で、なんでこうなるかというと、pop()
で取り払う時に
page.views.pop()
でpage.views
で最後のviewを取り払い、
top_view = page.views[-1]
で最後のviewを取得して、
page.go(top_view.route)
で最後のページに飛ぶ
という動作になっていて、
view_pop
では、1つ手前のページのrouteを取得したに過ぎないんですね。
この状態でpage.views.clear()
をしないとページがダブってしまうようです。
page.views.pop()
で最後のページ取り払ってるんじゃ?
って思ったんですが、どうやらpage.update()
をしないと、popしたことが反映されていない模様。
page.update()
をすると、その時点で1つ前にもどるので、
page.views.clear()
で全部取っ払わなくてもいいんじゃないかと思いまして。
じゃあ、route_change
で指示されたViewを開くだけでいいんじゃないかと
def route_change(route):
if page.route == '/':
page.views.append(
View(
"/",
[
AppBar(title=Text("index")),
ElevatedButton("Visit Doutonbori", on_click=lambda _: page.go("/doutonbori")),
],
)
)
if page.route == "/doutonbori":
page.views.append(
View(
"/doutonbori",
[
AppBar(title=Text("Doutonbori")),
ElevatedButton("Search Takoyaki", on_click=lambda _: page.go("/doutonbori/takoyaki")),
],
)
)
if page.route == "/doutonbori/takoyaki":
page.views.append(
View(
"/doutonbori/takoyaki",
[
AppBar(title=Text("Takoyaki")),
Text("たこ焼き食べたい"),
],
)
)
page.update()
def view_pop(view):
page.views.pop()
page.update()
page.on_route_change = route_change
page.on_view_pop = view_pop
page.go(page.route)
うんうん、やっぱりこっちのほうがスムーズ!
・・・あれ?indexのappbarにも戻るボタンがあるぞ・・・
・・・ポチ
全Viewが消せる仕様が爆誕したのでした!
じゃあ、メインビューはあらかじめpageに用意しておかないといけないってことね。
とうことで、
page.appbar = AppBar(title=Text("index"))
page.controls.append(ElevatedButton("Visit Doutonbori", on_click=lambda _: page.go("/doutonbori")))
def route_change(route):
if page.route == "/doutonbori":
page.views.append(
View(
"/doutonbori",
[
AppBar(title=Text("Doutonbori")),
ElevatedButton("Search Takoyaki", on_click=lambda _: page.go("/doutonbori/takoyaki")),
],
)
)
if page.route == "/doutonbori/takoyaki":
page.views.append(
View(
"/doutonbori/takoyaki",
[
AppBar(title=Text("Takoyaki")),
Text("たこ焼き食べたい"),
],
)
)
page.update()
def view_pop(view):
page.views.pop()
page.update()
page.on_route_change = route_change
page.on_view_pop = view_pop
page.go(page.route)
おお!これで完成ではないか!
必要な分だけ追加して、不要なものだけ取り除く!
なんだったんだ、あの分かり難い例は!
わっはっは!
はい、こっから泥沼
完成したかと思いきや、
最後のページまで行って最初に戻る、問題ない。
だけど、1ページだけ進んで戻ると、ボタンが押せない。。。押せないいいい!
どういうわけか、1ページだけ進んで戻ると、進むために押したボタンが効かなくなってしまう模様。
ボタンを複数用意したら違うボタンは機能する(ただし戻ると、今度はそのボタンがロックされる)
特にエラーログも吐いてないから、対処の仕様がない。
この不具合を理解できず、いろんなところにprint置いて動作を検証しながら四苦八苦
結局理由は分からんので、結果だけ載せると、
def view_pop(view):
page.views.pop()
+ if len(page.views) > 1:
page.update()
+ else : page.go('/')
page.views
が2枚以上あるときはpage.update()
残1枚のときはpage.go('/')
で矯正する荒治療で解決しました。
こんなんでええんやろか・・・
というか、そもそもこんな標準的な機能は元から搭載してほしいよ?
まさかこんなところでハマると思ってなかったので、備忘録として残しました。
もし、訪れた方がいたら温かい目で見てください。
全文
from flet import *
def main(page: Page):
page.title = "Osaka ni Oide"
page.appbar = AppBar(title=Text("index"))
page.controls.append(ElevatedButton("Visit Doutonbori", on_click=lambda _: page.go("/doutonbori")))
def route_change(route):
if page.route == "/doutonbori":
page.views.append(
View(
"/doutonbori",
[
AppBar(title=Text("Doutonbori")),
ElevatedButton("Search Takoyaki", on_click=lambda _: page.go("/doutonbori/takoyaki")),
],
)
)
if page.route == "/doutonbori/takoyaki":
page.views.append(
View(
"/doutonbori/takoyaki",
[
AppBar(title=Text("Takoyaki")),
Text("たこ焼き食べたい"),
],
)
)
page.update()
def view_pop(view):
page.views.pop()
if len(page.views) > 1:
page.update()
else : page.go('/')
page.on_route_change = route_change
page.on_view_pop = view_pop
page.go(page.route)
if __name__ == '__main__':
app(target=main)