目次
- 目次
- はじめに
- Windowを作る
- アクションバーを作る
- テキスト入力ボックスを作る
- ボタンのUIを作る
- スライダーUIを作る
- チェックボックスのUIを作る
- matplotlibのグラフをkivyの一部として利用する
- 二次元の地図データを埋め込む
- 参考資料
- MyEnigma Supporters
はじめに
先日、
PythonのマルチプラットフォームGUIライブラリである
Kivyを紹介しましたが、
今回は、Kivyによる基本的なGUIシステムの
作り方を紹介したいと思います。
また、この記事で紹介するすべてのサンプルコードは
下記のGitHubリポジトリでも公開されています。
また、下記のそれぞれのサンプルコードを、
Mac, Ubuntu, Windows, iOS(iPhone)で実行した
スクリーンショットも貼りました。
Windowを作る
もっとシンプルなサンプルとしては、
下記のコードで、上記のような
ウインドウタイトルと一つのラベルのみの
Windowを作ることができます。
from kivy.app import App from kivy.uix.button import Label from kivy.config import Config #Window sizeの設定 Config.set('graphics', 'width', '200') Config.set('graphics', 'height', '200') class TestApp(App): def build(self): self.title = 'Window Sample' self.icon = 'images.jpg' return Label(text='Hello World') TestApp().run()
また、iconメンバーに画像データを設定することで、
アプリのアイコンを設定することもできます。
(なぜかubuntuではアイコンがPythonのアイコンのままでした。。)
アクションバーを作る
下記のコードを実行すると、
PyQtのメニューバーに似た、
アクションバーを追加することができます。
デザインが結構かっこいいなと思います。
よく使う機能などをこのアクションバーに割り当てると便利です。
from kivy.app import App from kivy.uix.button import Label,Button from kivy.config import Config from kivy.uix.actionbar import ActionBar, ActionItem, ActionButton, ActionView, ActionPrevious, ActionGroup from kivy.uix.floatlayout import FloatLayout Config.set('graphics', 'width', '200') Config.set('graphics', 'height', '200') class MyActionBar(): def __init__(self): actionview = ActionView() actionview.use_separator=True ap = ActionPrevious(title='Action Bar', with_previous=False) actionview.add_widget(ap) self.abtn1=ActionButton(text="Btn1") self.abtn1.bind(on_press=self.ActionBtn1Callback) actionview.add_widget(self.abtn1) self.abtn2=ActionButton(text="Btn2") self.abtn2.bind(on_press=self.ActionBtn2Callback) actionview.add_widget(self.abtn2) self.abtn3=ActionButton(text="Btn3",icon="images.jpg") self.abtn3.bind(on_press=self.ActionBtn3Callback) actionview.add_widget(self.abtn3) group1=ActionGroup() self.abtn4=ActionButton(text="Btn4") self.abtn4.bind(on_press=self.ActionBtn4Callback) group1.add_widget(self.abtn4) self.abtn5=ActionButton(text="Press Me!!!!") self.abtn5.bind(on_press=self.ActionBtn5Callback) group1.add_widget(self.abtn5) actionview.add_widget(group1) self.actionbar=ActionBar() self.actionbar.add_widget(actionview) def ActionBtn1Callback(self,instance): print("Btn1 press!!") def ActionBtn2Callback(self,instance): print("Btn2 press!!") def ActionBtn3Callback(self,instance): print("Btn3 press!!") def ActionBtn4Callback(self,instance): print("Btn4 press!!") def ActionBtn5Callback(self,instance): print("Btn5 press!!") class RootWidget(FloatLayout): def __init__(self, **kwargs): # make sure we aren't overriding any important functionality super(RootWidget, self).__init__(**kwargs) # let's add a Widget to this layout self.add_widget( Button( text="Hello World", size_hint=(.5, .5), pos_hint={'center_x': .5, 'center_y': .5})) self.myactionbar=MyActionBar() self.add_widget( self.myactionbar.actionbar ) class TestApp(App): def build(self): self.root = root = RootWidget() self.title = 'Window Sample' self.icon = 'images.jpg' return self.root TestApp().run()
テキスト入力ボックスを作る
下記のコードを実行すると、
テキストボックス入力のUIを作ることができます。
下記のサンプルでは、
Clock.schedule_intervalを使って、
1秒毎に時刻のデータをテキストボックスに描画するようにしています。
残念ながら、
一行だけのテキストボックスを作る方法がわかりませんでした。
#!/usr/bin/python # -*- coding: utf-8 -*- from kivy.app import App from kivy.uix.button import Label,Button from kivy.config import Config from kivy.uix.boxlayout import BoxLayout from kivy.uix.textinput import TextInput from kivy.clock import Clock from datetime import datetime #Window sizeの設定 Config.set('graphics', 'width', '400') Config.set('graphics', 'height', '400') class RootWidget(BoxLayout): def __init__(self, **kwargs): super(RootWidget, self).__init__(padding=30, orientation='vertical') self.label=Label(text="Time Display") self.add_widget(self.label) Clock.schedule_interval(self.TimerCallback, 1.0) self.textinput = TextInput(text='Hello world', multiline=False) self.add_widget(self.textinput) def TimerCallback(self,dt): time=datetime.now().strftime("%Y/%m/%d %H:%M:%S") self.textinput.text=time class TestApp(App): def build(self): self.root = RootWidget() self.title = 'Text Input Sample' return self.root TestApp().run()
ボタンのUIを作る
下記がボタンを複数配置したUIのサンプルコードです。
boxlayoutで4つのAnchorlayoutを設定し、
その真ん中にAnchorlayoutの半分の大きさの
ボタンを配置しました。
#!/usr/bin/python # -*- coding: utf-8 -*- from kivy.app import App from kivy.uix.button import Label,Button from kivy.uix.gridlayout import GridLayout from kivy.uix.anchorlayout import AnchorLayout from kivy.core.window import Window class RootWidget(GridLayout): def __init__(self, **kwargs): super(RootWidget, self).__init__(cols=2) self.btn1=Button(text="Btn1",size_hint = (0.5, 0.5)) layout = AnchorLayout(anchor_x='center', anchor_y='center') layout.add_widget(self.btn1) self.add_widget(layout) self.btn2=Button(text="Btn2",size_hint = (0.5, 0.5)) layout2 = AnchorLayout(anchor_x='center', anchor_y='center') layout2.add_widget(self.btn2) self.add_widget(layout2) self.btn3=Button(text="Btn3",size_hint = (0.5, 0.5)) layout3 = AnchorLayout(anchor_x='center', anchor_y='center') layout3.add_widget(self.btn3) self.add_widget(layout3) self.btn4=Button(text="Btn4",size_hint = (0.5, 0.5)) layout4 = AnchorLayout(anchor_x='center', anchor_y='center') layout4.add_widget(self.btn4) self.add_widget(layout4) def on_checkbox_active(self, checkbox, value): if value: print('The checkbox', checkbox, 'is active') else: print('The checkbox', checkbox, 'is inactive') class TestApp(App): def build(self): self.root = RootWidget() self.title = 'Text Input Sample' return self.root TestApp().run()
スライダーUIを作る
下記がスライダーUIを使ったサンプルコードです。
スライダーが移動された時に、
Callback関数を呼んで、
Labelにスライダーの値を表示させています。
from kivy.app import App from kivy.uix.button import Label,Button from kivy.config import Config from kivy.uix.boxlayout import BoxLayout from kivy.uix.slider import Slider #Window sizeの設定 Config.set('graphics', 'width', '200') Config.set('graphics', 'height', '200') class RootWidget(BoxLayout): def __init__(self, **kwargs): super(RootWidget, self).__init__(padding=50) self.label=Label(text="Please slide the slider") self.add_widget(self.label) self.slider = Slider(min=-100, max=100, value=25) self.slider.bind(value=self.callback) self.add_widget(self.slider) def callback(self,instance,value): self.label.text=str(value) class TestApp(App): def build(self): self.root = root = RootWidget() self.title = 'Slider Sample' return self.root TestApp().run()
チェックボックスのUIを作る
下記はチェックボックスを作るサンプルコードです。
checkbox.valueの値から、
チェックボックスの状態を確認することができます。
#!/usr/bin/python # -*- coding: utf-8 -*- from kivy.app import App from kivy.uix.button import Label,Button from kivy.config import Config from kivy.uix.gridlayout import GridLayout from kivy.uix.checkbox import CheckBox from kivy.core.window import Window Window.clearcolor = (0.7, 0.7, 0.7, 0.7) class RootWidget(GridLayout): def __init__(self, **kwargs): super(RootWidget, self).__init__(cols=2) self.label=Label(text="Check 1") self.add_widget(self.label) self.checkbox = CheckBox() self.checkbox.bind(active=self.on_checkbox_active) self.add_widget(self.checkbox) self.label=Label(text="Check 2") self.add_widget(self.label) checkbox1 = CheckBox() self.add_widget(checkbox1) self.label=Label(text="Check 3") self.add_widget(self.label) checkbox3 = CheckBox() self.add_widget(checkbox3) def on_checkbox_active(self, checkbox, value): if value: print('The checkbox', checkbox, 'is active') else: print('The checkbox', checkbox, 'is inactive') class TestApp(App): def build(self): self.root = RootWidget() self.title = 'Text Input Sample' return self.root TestApp().run()
matplotlibのグラフをkivyの一部として利用する
pythonのグラフ作成ライブラリmatplotlibは
グラフ作成に非常に便利です。
このkivyのアドオン管理ツールである、
kivy gardenを使うことにより、
簡単にmatplotlibのグラフをkivyのwidgetの一部として
GUIツールの一部に組み込むことができます。
まず初めに、下記のコマンドでkivy gardenをインストールし、
$ pip install kivy-garden
gardenコマンドでmatplotlibとkivyを繋ぐアドオンをインストールします。
$ garden install matplotlib
あとは、下記のサンプルを起動すると、
冒頭のようなmatplotlibのグラフを
kivyの一部として組み込むことができます。
from kivy.app import App from kivy.uix.boxlayout import BoxLayout from kivy.uix.label import Label from kivy.config import Config import numpy as np import matplotlib matplotlib.use('module://kivy.garden.matplotlib.backend_kivy') import matplotlib.pyplot as pl import sys, os class GraphView(BoxLayout): def __init__(self, **kwargs): super(GraphView, self).__init__(orientation='vertical') self.add_widget(Label(text="embeded matplotlib sample")) self.add_widget(self.graph_plot_sample()) def graph_plot_sample(self): self.fig, ax = pl.subplots() x = np.linspace(-np.pi, np.pi) y = np.sin(x) ax.set_xlabel("X label") ax.set_ylabel("Y label") ax.grid(True) ax.plot(x, y) return self.fig.canvas class GraphApp(App): def build(self): height = 300 Config.set('graphics', 'height', height) Config.set('graphics', 'width', height * 2) return GraphView() if __name__ == '__main__': GraphApp().run()
下記のコードを参考にさせて頂きました。
https://github.com/Himenon/SampleKivy/tree/master/matplotlibgithub.com
二次元の地図データを埋め込む
下記のgardenコマンドでmapviewをインストールすると、
$ pip install futures requests
$ garden install mapview
二次元の地図のデータを
kivyアプリに入れることができます。
from kivy.garden.mapview import MapView from kivy.app import App class MapViewApp(App): def build(self): mapview = MapView(zoom=15, lat=35.681382, lon=139.766084) return mapview MapViewApp().run()
下記のリンクのように地図にピンを打つこともできます。
ちなみにGoogle Earthにピンを打ちたい場合は
こちらのツールが便利だと思います。
参考資料
MyEnigma Supporters
もしこの記事が参考になり、
ブログをサポートしたいと思われた方は、
こちらからよろしくお願いします。