Kivy は最近人気のある Python のクロスプラットフォームな GUI のフレームワーク。 今回はそんな Kivy で作った GUI 上に Matplotlib のグラフをプロットしてみる。
使った環境は次の通り。
$ sw_vers ProductName: Mac OS X ProductVersion: 10.14.5 BuildVersion: 18F132 $ python -V Python 3.7.3
下準備
まずは Kivy と Matplotlib をインストールしておく。
$ pip install kivy matplotlib numpy
続いて Kivy Garden を使って Matplotlib 用のプラグイン (garden.matplotlib) をインストールする。
$ garden install matplotlib
これで Kivy で Matplotlib を使う準備ができた。
Kivy で Matplotlib のグラフをプロットする
以下の Kivy で Matplotlib のグラフをプロットするサンプルコードを示す。
garden.matplotlib を使うと Figure#canvas
のインスタンスをウィジェットとして追加できるようになる。
#!/usr/bin/env python # -*- coding: utf-8 -*- from kivy.app import App from kivy.uix.boxlayout import BoxLayout from kivy.uix.label import Label import numpy as np import matplotlib.pyplot as plt import matplotlib # Kivy 上で Matplotlib を使うために必要な準備 matplotlib.use('module://kivy.garden.matplotlib.backend_kivy') class GraphApp(App): """Matplotlib のグラフを表示するアプリケーション""" def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.title = 'Matplotlib graph on Kivy' def build(self): # メインの画面 main_screen = BoxLayout() main_screen.orientation = 'vertical' # 上部にラベルを追加しておく label_text = 'The following is a graph of Matplotlib' label = Label(text=label_text) label.size_hint_y = 0.2 main_screen.add_widget(label) # サイン波のデータを用意する x = np.linspace(-np.pi, np.pi, 100) y = np.sin(x) # 描画する領域を用意する fig, ax = plt.subplots() # プロットする ax.plot(x, y) # Figure#canvas をウィジェットとして追加する main_screen.add_widget(fig.canvas) return main_screen def main(): # アプリケーションを開始する app = GraphApp() app.run() if __name__ == '__main__': main()
上記を実行する。
$ python kvplot.py
すると、次のような結果が得られる。
ちゃんと描画できてるね。
FigureCanvasKivyAgg を使う場合
別のやり方として Figure オブジェクトを FigureCanvasKivyAgg
でラップするやり方もある。
サンプルコードは次の通り。
#!/usr/bin/env python # -*- coding: utf-8 -*- from kivy.app import App from kivy.uix.boxlayout import BoxLayout from kivy.garden.matplotlib.backend_kivyagg import FigureCanvasKivyAgg from kivy.uix.label import Label import numpy as np import matplotlib.pyplot as plt class GraphApp(App): """Matplotlib のグラフを表示するアプリケーション""" def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.title = 'Matplotlib graph on Kivy' def build(self): main_screen = BoxLayout() main_screen.orientation = 'vertical' label_text = 'The following is a graph of Matplotlib' label = Label(text=label_text) label.size_hint_y = 0.2 main_screen.add_widget(label) x = np.linspace(-np.pi, np.pi, 100) y = np.sin(x) fig, ax = plt.subplots() ax.plot(x, y) # Figure をラップする widget = FigureCanvasKivyAgg(fig) # ウィジェットとして追加する main_screen.add_widget(widget) return main_screen def main(): app = GraphApp() app.run() if __name__ == '__main__': main()
表示される内容は変わらない。
ウィジェットのクラスとして定義する
さらに、ウィジェットをクラスとして定義した上で、その中にグラフを埋め込む場合には、次のようにする。
#!/usr/bin/env python # -*- coding: utf-8 -*- from kivy.app import App from kivy.uix.boxlayout import BoxLayout from kivy.uix.label import Label from kivy.garden.matplotlib.backend_kivyagg import FigureCanvasKivyAgg import numpy as np import matplotlib.pyplot as plt class GraphView(BoxLayout): """Matplotlib のグラフを表示するためのウィジェット""" def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) x = np.linspace(-np.pi, np.pi, 100) y = np.sin(x) fig, ax = plt.subplots() ax.plot(x, y) widget = FigureCanvasKivyAgg(fig) self.add_widget(widget) class GraphApp(App): """Matplotlib のグラフを表示するアプリケーション""" def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.title = 'Matplotlib graph on Kivy' def build(self): main_screen = BoxLayout() main_screen.orientation = 'vertical' label_text = 'The following is a graph of Matplotlib' label = Label(text=label_text) label.size_hint_y = 0.2 main_screen.add_widget(label) # ウィジェットを生成して追加する graph = GraphView() main_screen.add_widget(graph) return main_screen def main(): # アプリケーションを開始する app = GraphApp() app.run() if __name__ == '__main__': main()
こちらも表示される内容は変わらない。
KV 言語を使う
Kivy は KV 言語という DSL でレイアウトを制御できる。 もし、KV 言語も併用したいという場合であれば次のようにする。
#!/usr/bin/env python # -*- coding: utf-8 -*- from kivy.app import App from kivy.uix.boxlayout import BoxLayout from kivy.uix.label import Label from kivy.lang import Builder from kivy.garden.matplotlib.backend_kivyagg import FigureCanvasKivyAgg import numpy as np import matplotlib.pyplot as plt kv_def = ''' <RootWidget>: orientation: 'vertical' Label: text: 'The following is a graph of Matplotlib' size_hint_y: 0.2 GraphView: <GraphView>: ''' Builder.load_string(kv_def) class GraphView(BoxLayout): """Matplotlib のグラフを表示するためのウィジェット""" def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) x = np.linspace(-np.pi, np.pi, 100) y = np.sin(x) fig, ax = plt.subplots() ax.plot(x, y) widget = FigureCanvasKivyAgg(fig) self.add_widget(widget) class RootWidget(BoxLayout): """子を追加していくためのウィジェットを用意しておく""" class GraphApp(App): """Matplotlib のグラフを表示するアプリケーション""" def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.title = 'Matplotlib graph on Kivy' def build(self): return RootWidget() def main(): # アプリケーションを開始する app = GraphApp() app.run() if __name__ == '__main__': main()
こちらも表示される内容は変わらない。
グラフで表示される内容を動的に更新したい
グラフに表示される内容を動的に更新したい場合のサンプルも以下に示す。 基本的には普通に Matplotlib を使って動的なグラフを描くのと変わらない。
#!/usr/bin/env python # -*- coding: utf-8 -*- from kivy.app import App from kivy.uix.boxlayout import BoxLayout from kivy.clock import Clock from kivy.lang import Builder from kivy.garden.matplotlib.backend_kivyagg import FigureCanvasKivyAgg import numpy as np import matplotlib.pyplot as plt kv_def = ''' <RootWidget>: orientation: 'vertical' Label: text: 'The following is a graph of Matplotlib' size_hint_y: 0.2 GraphView: <GraphView>: ''' Builder.load_string(kv_def) class GraphView(BoxLayout): """Matplotlib のグラフを表示するためのウィジェット""" def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # 初期化に用いるデータ x = np.linspace(-np.pi, np.pi, 100) y = np.sin(x) # 描画状態を保存するためのカウンタ self.counter = 0 # Figure, Axis を保存しておく self.fig, self.ax = plt.subplots() # 最初に描画したときの Line も保存しておく self.line, = self.ax.plot(x, y) # ウィジェットとしてグラフを追加する widget = FigureCanvasKivyAgg(self.fig) self.add_widget(widget) # 1 秒ごとに表示を更新するタイマーを仕掛ける Clock.schedule_interval(self.update_view, 0.01) def update_view(self, *args, **kwargs): # データを更新する self.counter += np.pi / 100 # 10 分の pi ずらす # ずらした値を使ってデータを作る x = np.linspace(-np.pi + self.counter, np.pi + self.counter, 100) y = np.sin(x) # Line にデータを設定する self.line.set_data(x, y) # グラフの見栄えを調整する self.ax.relim() self.ax.autoscale_view() # 再描画する self.fig.canvas.draw() self.fig.canvas.flush_events() class RootWidget(BoxLayout): """子を追加していくためのウィジェットを用意しておく""" class GraphApp(App): """Matplotlib のグラフを表示するアプリケーション""" def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.title = 'Matplotlib graph on Kivy' def build(self): return RootWidget() def main(): # アプリケーションを開始する app = GraphApp() app.run() if __name__ == '__main__': main()
実行すると、こんな表示が得られる。 うにょうにょ。
いじょう。
スマートPythonプログラミング: Pythonのより良い書き方を学ぶ
- 作者: もみじあめ
- 発売日: 2016/03/12
- メディア: Kindle版
- この商品を含むブログ (1件) を見る