実現したいこと
pythonでお手軽にクロスプラットフォームなGUIアプリを作りたいと思っています。
(最終的には経済関係のデータセットを読み込んで、自前で分析を行うGUIアプリを作りたいと思っています。)
前提
検索したところfletというライブラリが出てきました。参考サイトも見つかり、サンプルで提示いただいているclassを参考に、irisデータセットを読み込み、データセットの列名をドロップダウンで選択して、ボタンを押すとplotlyのfigureを描画するスクリプトを作りたいと思っています。
発生している問題・エラーメッセージ
下記図のように、plotlyのコントロールを使って、何とかGUIとして表示できるところまでは到達したのですが、「グラフを更新」ボタンを押下してもplotlyのグラフが切り替わりません。
flet公式にある、PlotlyChartの説明などを見ても、上記問題の解決ができず、困ってます。
PlotlyChartの.update()をコールしないといけないのかと思ったのですが、その場合、下記のようなエラーが出てしまいます。(PlotlyChart自体は配置しているにもかかわらず)
エラーメッセージ AssertionError: Control must be added to the page first.
正直、イベントを受けるときの書き方が根本的に書き方がまずいのかもしれないと思い、解決方法のほかに、可能であれば、plotlyの描画コンポーネントをfletで作る場合に上記のような書き方がまずいのかどうかも含めて、ご指摘、アドバイス等いただけないでしょうか。(独学のため、pythonにおける適切なクラスの書き方、設計方法などは理解が不足している可能性が高いです)
該当のソースコード
Python
1# fletテスト 2import flet as ft 3import pandas as pd 4import plotly.express as px 5from flet.plotly_chart import PlotlyChart 6import pandas as pd 7 8# irisデータセットをダウンロード 9# df = pd.read_csv("https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data", header=None) 10# df.columns = ["sepal_length", "sepal_width", "petal_length", "petal_width", "species"] 11 12# グラフを描画するコントロールクラス 13class IrisGraph(ft.UserControl): 14 def build(self): 15 self.input_df = pd.read_csv("iris.csv") 16 # ドロップダウンで選択できるパラメータのリスト 17 # params = ["sepal_length", "sepal_width", "petal_length", "petal_width"] 18 params = self.input_df.columns.to_list() 19 # ドロップダウンで選択できるグラフの種類のリスト 20 types = ["scatter", "box", "treemap"] 21 22 # ドロップダウンを作成 23 self.x_dropdown = ft.Dropdown( 24 value=params[0], label="x", 25 options=[ft.dropdown.Option(i) for i in params] 26 ) 27 self.y_dropdown = ft.Dropdown( 28 value=params[1], label="y", 29 options=[ft.dropdown.Option(i) for i in params] 30 ) 31 # self.color_dropdown = ft.Dropdown( 32 # items=params + ["species"], value="species", label="color" 33 # ) 34 self.color_dropdown = ft.Dropdown( 35 value=params[2], label="color", 36 options=[ft.dropdown.Option(i) for i in params] 37 ) 38 self.type_dropdown = ft.Dropdown( 39 value=types[0], label="type", 40 options=[ft.dropdown.Option(i) for i in types] 41 ) 42 # ドロップダウンからパラメータとグラフの種類を取得 43 self.x = self.x_dropdown.value 44 self.y = self.y_dropdown.value 45 self.g_color = self.color_dropdown.value 46 self.g_type = self.type_dropdown.value 47 48 # # ドロップダウンの値が変更されたときに呼び出されるメソッドを設定 49 # self.x_dropdown.on_change(self.on_change()) 50 # self.y_dropdown.on_change(self.on_change()) 51 # self.color_dropdown.on_change(self.on_change()) 52 # self.type_dropdown.on_change(self.on_change()) 53 54 # ボタンでグラフを更新 55 self.update_button = ft.ElevatedButton( 56 text="グラフを更新", on_click=self.update_graph 57 ) 58 59 # グラフオブジェクトを作成 60 self.fig = px.scatter(self.input_df, x=self.x, y=self.y, color=self.g_color) 61 self.graph = PlotlyChart(self.fig) 62 63 # 初期グラフを描画 64 # self.update_graph() 65 66 # コントロールを配置 67 return ft.Card( 68 content=ft.Container( 69 content=ft.Column( 70 controls=[ 71 ft.Row( 72 controls=[ 73 self.x_dropdown, 74 self.y_dropdown, 75 ], 76 alignment=ft.MainAxisAlignment.SPACE_AROUND, 77 ), 78 ft.Row( 79 controls=[ 80 self.color_dropdown, 81 self.type_dropdown, 82 self.update_button, 83 ], 84 alignment=ft.MainAxisAlignment.SPACE_AROUND, 85 ), 86 self.graph, 87 ], 88 alignment=ft.MainAxisAlignment.SPACE_AROUND, 89 ), 90 width=800, 91 padding=16, 92 ) 93 ) 94 95 # def on_change(self, sender: ft.Control): 96 # def on_change(self, value): 97 # # ドロップダウンの値が変更されたときにグラフを再描画する 98 # self.draw_graph() 99 100 # def draw_graph(self): 101 def update_graph(self, e: ft.UserControl): 102 # グラフの種類に応じてグラフオブジェクトを作成 103 if self.g_type == "scatter": 104 fig = px.scatter(self.input_df, x=self.x, y=self.y, color=self.g_color) 105 elif self.g_type == "box": 106 fig = px.box(self.input_df, x=self.x, y=self.y, color=self.g_color) 107 elif self.g_type == "treemap": 108 fig = px.treemap(self.input_df, path=[self.g_color], values=self.x) 109 else: 110 fig = None 111 self.graph = PlotlyChart(self.fig) 112 # グラフオブジェクトを更新 113 # self.graph.update() 114 # if fig is not None: 115 # self.graph.update() # updateをかけるといいのかな?と思ったけどエラーが出る。 116 117 118def main(page: ft.Page): 119 # ページにコントロールを追加 120 page.add(IrisGraph()) 121 122 123# アプリを実行 124ft.app(target=main)
試したこと
・flet公式の記載を確認(イベント回り、PlotlyChartのところ)
・flet関連記事の確認
・BING(GPT-4)に確認しつつリファクタリングを実施
補足情報(FW/ツールのバージョンなど)
python : 3.10.5
flet: 0.6.2
pandas:1.4.4
plotly:5.10.0

あなたの回答
tips
プレビュー