Kivy入門(version1系)

Kivy入門(version1系)

目次

1 概要

  • Pythonのライブラリ
  • クロスプラットフォームの開発環境
  • Kivy + buildozer で Androidアプリを作ってみる
  • 環境は Ubuntu version 20.04ベースで行う(Dockerを利用すれば、Dockerを利用できる他のプラットフォームでも同じ手順で行える)

2 関連リンク

2.1 使うかもしれないパッケージ

3 インストール

3.1 以下の操作を行っている動画

3.2 kivyのUbuntu20.04へのインストール手順

  • 手順の確認はDockerのUbuntu 20.04を利用した
  • 以下の手順で共有ディレクトリを作成し、Dockerは1000のuidのユーザーで行った
sudo mkdir /work/kivy
sudo chown 1000.1000 /work/kivy/
  • 起動は以下のコマンドで行った
docker run -it --rm -v /work/kivy:/home/ ubuntu:20.04 

3.3 手順

3.3.1 必要パッケージのインストール

apt update
apt install python3-kivy 
  • 一般ユーザーで以下を行う場合は 以下のように先頭に sudoをつける
sudo apt update
sudo apt install python3-kivy 

4 空のApp作成

4.1 以下の説明を行っている動画

4.2 空のApp作成手順

  • tutorial001.py というファイル名で以下内容のファイル作成
from kivy.app import App

class HelloWorldApp(App):
  pass

if __name__ == '__main__':
    HelloWorldApp().run()

4.2.1 実行

python3 tutorial002_helloworld.py 

4.3 この章のまとめ

  • 空のアプリ作成

5 サンプル用のHello Worldプログラム作成(Label利用)

5.1 以下の説明を行っている動画

5.2 HelloWorld

  • tutorial002_helloworld.py というファイル名で以下内容のファイル作成
from kivy.app import App
from kivy.uix.label import Label

class HelloWorldApp(App):

    def build(self):
        return Label(text='Hello World!')

if __name__ == '__main__':
    HelloWorldApp().run()

5.2.1 実行

python3 tutorial002_helloworld.py 

5.3 この章のまとめ

  • Labelを利用して、Hello World作成

6 BoxLayout

6.1 以下の説明を行っている動画

6.3 BoxLayout利用

  • tutorial003_boxlayout.py というファイル名で以下内容のファイル作成
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout

class HelloWorldApp(App):
    def build(self):
        b = BoxLayout(orientation="vertical")
        l1 = Label(text='Hello',font_size=150)
        l2 = Label(text='World',font_size=150)

        b.add_widget(l1)
        b.add_widget(l2)
        return b

if __name__ == '__main__':
    HelloWorldApp().run()

6.3.1 実行

python3 tutorial003_boxlayout.py

6.4 この章のまとめ

  • 部品を良い感じで並べてくれるツールの内BoxLayoutを使ってみた

7 Module: kivy.lang.builder

7.1 以下の説明を行っている動画

7.3 Builder 利用

  • tutorial004_builder.py というファイル名で以下内容のファイル作成
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
from kivy.lang.builder import Builder

kv='''
BoxLayout:
    orientation: 'vertical'
    Label:
        text: 'Hello'
        font_size: 150
    Label:
        text: 'World'
        font_size: 150
'''

class HelloWorldApp(App):
    def build(self):
        return Builder.load_string(kv)

if __name__ == '__main__':
    HelloWorldApp().run()

7.3.1 実行

python3 tutorial004_builder.py

7.4 この章のまとめ

  • builderを利用して、kivy言語を利用

8 Kivy言語の利用(外部ファイル)

8.1 以下の説明を行っている動画

8.3 Kivy言語外部ファイルを利用

8.3.1 tutorial005_kivy.py というファイル名で以下内容のファイル作成

from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
#from kivy.uix.widget import Widget
#from kivy.lang.builder import Builder

class HelloWorld(BoxLayout):
  pass

class Tutorial005App(App):
    def build(self):
        return HelloWorld()

if __name__ == '__main__':
    Tutorial005App().run()

8.3.2 tutorial005.kv ファイルを以下の内容で作成

  • ファイル名はAppを継承したクラス名の最後のAppを除いた物が自動で検索される
  • 例 今回だと Tutorial005App から tutorial005.kv
  • 例 TutorialApp なら tutorial.kv
<HelloWorld>:
    orientation: 'vertical'
    Label:
	text: 'Hello'
	font_size: 150
    Label: 
	text: 'World'
	font_size: 150

8.3.3 実行

python3 tutorial005_builder.py

8.4 この章のまとめ

  • 外部ファイルで、kivy言語を利用

9 Module: kivy.uix.button

9.1 以下の説明を行っている動画

9.3 buttonを利用する手順例

9.3.1 tutorial006.py というファイル名で以下内容のファイル作成

  • on_release でボタン押して離した時にイベント発生する記述を行う
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
from kivy.lang.builder import Builder

import random

kv='''
<HelloWorld>
    orientation: 'vertical'
    Label:
        id: label1
        text: 'Hello'
        font_size: 150
    Button:
        text: 'Change Color'
        font_size: 80
        on_release: root.changeColor()
''' 

Builder.load_string(kv)

class HelloWorld(BoxLayout):
    def changeColor(self):
        print("changeColor")
        for key, val in self.ids.items():
            print("key={0}, val={1}".format(key, val))
        print(self.ids)
        mylabel=self.ids['label1']
        mylabel.color=[random.random(),random.random(),random.random(),1]

class HelloWorldApp(App):
    def build(self):
        return HelloWorld()
        #return Builder.load_string(kv)

if __name__ == '__main__':
    HelloWorldApp().run()

9.3.2 実行

  • Ubuntuでは pythonではなくpython3の必要あるケースあり
python tutorial006.py 

9.3.3 tutorial006-2.py というファイル名で以下内容のファイル作成

  • kivy言語側で、クリックイベントの処理記述
  • kivy言語側で、randomモジュール読み込み
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
from kivy.lang.builder import Builder

import random

kv='''
#:import random random
<HelloWorld>
    orientation: 'vertical'
    Label:
        id: label1
        text: 'Hello'
        font_size: 150
    Button:
        text: 'Change Color'
        font_size: 80
        on_release: root.ids['label1'].color=[random.random(),random.random(),random.random(),1]
''' 

Builder.load_string(kv)

class HelloWorld(BoxLayout):
    pass

class HelloWorldApp(App):
    def build(self):
        return HelloWorld()
        #return Builder.load_string(kv)

if __name__ == '__main__':
    HelloWorldApp().run()

9.3.4 実行

  • Ubuntuでは pythonではなくpython3の必要あるケースあり
python tutorial006-2.py 

9.4 この章のまとめ

  • Module: kivy.uix.buttonを使ってみた
  • ボタンを押して離した時にイベント発生する処理を書いた

10 Module: kivy.uix.textinputを利用して足し算アプリ作成

10.1 以下の説明を行っている動画

10.3 Module: kivy.uix.textinputを利用して足し算アプリ作成 手順

10.3.1 tutorial007.py というファイル名で以下内容のファイル作成

  • input_filterで整数のみ入力可能にしてある
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.textinput import TextInput
from kivy.lang.builder import Builder

import random

# https://kivy.org/doc/stable/api-kivy.uix.textinput.html

kv='''
#:import random random
<HelloWorld>
    orientation: 'vertical'
    TextInput:
        id: textinput1
        font_size: 150
        input_filter: 'int'
        text: '1'
    TextInput:
        id: textinput2
        font_size: 150
        input_filter: 'int'
        text: '1'
    Label:
        id: label1
        text: ''
        font_size: 150
    Button:
        text: 'calc add'
        font_size: 80
        on_release: root.ids['label1'].text=str(int(root.ids['textinput1'].text)+int(root.ids['textinput2'].text))

''' 

Builder.load_string(kv)

class HelloWorld(BoxLayout):
    pass

class HelloWorldApp(App):
    def build(self):
        return HelloWorld()
        #return Builder.load_string(kv)

if __name__ == '__main__':
    HelloWorldApp().run()

10.3.2 実行

python3 tutorial007.py 

10.4 この章のまとめ

  • Module: kivy.uix.textinputの基本的な使い方紹介
  • Module: kivy.uix.textinputを利用して足し算アプリ作成

11 設定を行う機能

11.1 以下の説明を行っている動画

11.3 設定を行う機能の利用手順

11.3.1 tutorial008.py というファイル名で以下内容のファイル作成

  • ホームディレクトリの .kivy/config.ini というファイルが設定を変更すると更新される
  • app.open_settings() でセッティング画面が表示される
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.textinput import TextInput
from kivy.lang.builder import Builder

import random

kv='''
#:import random random
<MyAdd>
    orientation: 'vertical'
    TextInput:
        id: textinput1
        font_size: 100
        input_filter: 'int'
        text: '1'
    TextInput:
        id: textinput2
        font_size: 100
        input_filter: 'int'
        text: '1'
    Label:
        id: label1
        text: ''
        font_size: 100
    Button:
        text: 'calc add'
        font_size: 80
        on_release: root.ids['label1'].text=str(int(root.ids['textinput1'].text)+int(root.ids['textinput2'].text))
    Button:
        text: 'setting'
        font_size: 80
        on_release: app.open_settings()
''' 

Builder.load_string(kv)

class MyAdd(BoxLayout):
    pass

class HelloWorldApp(App):
    def build(self):
        return MyAdd()
        #return Builder.load_string(kv)

if __name__ == '__main__':
    HelloWorldApp().run()

11.3.2 実行

python3 tutorial008.py

11.3.3 tutorial008-2.py というファイル名で以下内容のファイル作成

  • ホームディレクトリの .kivy/config.ini というファイルが設定を変更すると更新される
  • app.open_settings() でセッティング画面が表示される
  • self.settings_cls=SettingsWithSidebar を追加すると横にメニューが追加
  • self.use_kivy_settings=False の行の#を外して有効化すると、元々のメニューは選択できなくなる
  • 独自メニュー追加
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.textinput import TextInput
from kivy.uix.settings import SettingsWithSidebar
from kivy.lang.builder import Builder

import json
import random

Builder.load_string('''
#:import random random
<MyAdd>
    orientation: 'vertical'
    TextInput:
        id: textinput1
        font_size: 100
        input_filter: 'int'
        text: '1'
    TextInput:
        id: textinput2
        font_size: 100
        input_filter: 'int'
        text: '1'
    Label:
        id: label1
        text: ''
        font_size: 100
    Button:
        text: 'calc add'
        font_size: 80
        on_release: root.ids['label1'].text=str(int(root.ids['textinput1'].text)+int(root.ids['textinput2'].text))
    Button:
        text: 'setting'
        font_size: 80
        on_release: app.open_settings()
''')

settings_json=json.dumps([
    {'type': 'title', 'title': 'example title'},
    {'type': 'bool', 'title': 'a boolean setting', 'desc': 'Boolean description text', 'section':'example', 'key':'boolexample'},
    {'type': 'numeric', 'title': 'a numerical setting', 'desc': 'Numeric description text', 'section':'example', 'key':'numericalexample'},
    {'type': 'options', 'title': 'a options setting', 'desc': 'Option description text', 'section':'example', 'key':'optionsexample', 'options':['1','2','3']},
    {'type': 'string', 'title': 'a string setting', 'desc': 'String description text', 'section':'example', 'key':'stringexample'},
    {'type': 'path', 'title': 'a path setting', 'desc': 'Path description text', 'section':'example', 'key':'pathexample'},
    ])

class MyAdd(BoxLayout):
    pass

class HelloWorldApp(App):
    def build(self):
        self.settings_cls=SettingsWithSidebar
        # self.use_kivy_settings=False
        setting1 = self.config.get('example', 'optionsexample')
        print(self.config.items('example'))
        return MyAdd()
        #return Builder.load_string(kv)

    def build_config(self, config):
        config.setdefaults('example', {
            'boolexample':True,
            'numericalexample':1,
            'optionsexample':'3',
            'stringexample':'abc',
            'pathexample':'./',
            })

    def build_settings(self, settings):
        settings.add_json_panel('test', self.config, data=settings_json)

    def on_config_change(self, config, section, key, value):
        print([config, section, key, value])

if __name__ == '__main__':
    HelloWorldApp().run()

11.3.4 実行

python3 tutorial008-2.py

11.4 この章のまとめ

  • ベースはCrash Courseの13番目の動画を参考に作成
  • 設定関係の説明を行った
  • 独自メニューの追加方法も紹介

12 スクリーンマネジャー(画面切替)

12.1 以下の説明を行っている動画

12.3 スクリーンマネジャー(画面切替) 手順

12.3.1 tutorial009.py というファイル名で以下内容のファイル作成

  • スクリーンマネジャーはScreenManagerを継承
  • 切り替える画面はScreenを継承
  • クラスの定義はkivy言語の読み込み前に行わないとエラーになっていた
  • kivy.uix.screenmanager.FadeTransitionをkivy言語側でインポート
  • transition: FadeTransition() の 先頭の#をはずすと、画面切替の様子が変更になる
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.textinput import TextInput
from kivy.uix.settings import SettingsWithSidebar
from kivy.lang.builder import Builder
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition

import json
import random

class MyScreenManager(ScreenManager):
    pass

class MyAdd(Screen):
    pass

class MySub(Screen):
    pass

root_widget = Builder.load_string('''
#:import random random
#:import FadeTransition kivy.uix.screenmanager.FadeTransition

MyScreenManager:
    #transition: FadeTransition()
    MyAdd:
    MySub:

<MyAdd>
    name : 'MyAdd'
    BoxLayout:
        orientation: 'vertical'
        TextInput:
            id: textinput1
            font_size: 100
            input_filter: 'int'
            text: '1'
        TextInput:
            id: textinput2
            font_size: 100
            input_filter: 'int'
            text: '1'
        Label:
            id: label1
            text: ''
            font_size: 100
        Button:
            text: 'calc add'
            font_size: 80
            on_release: root.ids['label1'].text=str(int(root.ids['textinput1'].text)+int(root.ids['textinput2'].text))
        Button:
            text: 'setting'
            font_size: 80
            on_release: app.open_settings()
        Button:
            text: 'go to sub'
            font_size: 80
            on_release: app.root.current = 'MySub'
<MySub>
    name : 'MySub'
    BoxLayout:
        orientation: 'vertical'
        TextInput:
            id: textinput1
            font_size: 100
            input_filter: 'int'
            text: '1'
        TextInput:
            id: textinput2
            font_size: 100
            input_filter: 'int'
            text: '1'
        Label:
            id: label1
            text: ''
            font_size: 100
        Button:
            text: 'calc sub'
            font_size: 80
            on_release: root.ids['label1'].text=str(int(root.ids['textinput1'].text)-int(root.ids['textinput2'].text))
        Button:
            text: 'setting'
            font_size: 80
            on_release: app.open_settings()
        Button:
            text: 'go to add'
            font_size: 80
            on_release: app.root.current = 'MyAdd'
''')

# ここで定義するとエラーに
#class MyScreenManager(ScreenManager):
#    pass
#
#class MyAdd(Screen):
#    pass
#
#class MySub(Screen):
#    pass
#

settings_json=json.dumps([
    {'type': 'title', 'title': 'example title'},
    {'type': 'bool', 'title': 'a boolean setting', 'desc': 'Boolean description text', 'section':'example', 'key':'boolexample'},
    {'type': 'numeric', 'title': 'a numerical setting', 'desc': 'Numeric description text', 'section':'example', 'key':'numericalexample'},
    {'type': 'options', 'title': 'a options setting', 'desc': 'Option description text', 'section':'example', 'key':'optionsexample', 'options':['1','2','3']},
    {'type': 'string', 'title': 'a string setting', 'desc': 'String description text', 'section':'example', 'key':'stringexample'},
    {'type': 'path', 'title': 'a path setting', 'desc': 'Path description text', 'section':'example', 'key':'pathexample'},
    ])


class HelloWorldApp(App):
    def build(self):
        self.settings_cls=SettingsWithSidebar
        self.use_kivy_settings=False
        setting1 = self.config.get('example', 'optionsexample')
        print(self.config.items('example'))
        return root_widget
        #return Builder.load_string(kv)

    def build_config(self, config):
        config.setdefaults('example', {
            'boolexample':True,
            'numericalexample':1,
            'optionsexample':'3',
            'stringexample':'abc',
            'pathexample':'./',
            })

    def build_settings(self, settings):
        settings.add_json_panel('test', self.config, data=settings_json)

    def on_config_change(self, config, section, key, value):
        print([config, section, key, value])

if __name__ == '__main__':
    HelloWorldApp().run()

12.3.2 実行

python3 tutorial009.py

12.4 この章のまとめ

13 今後

  • 今後も文書追加していきます。

14 この文書のチェンジログ

  • 2020/08/13 初版
  • 2020/08/14 Module: kivy.lang.builder の章, Module: kivy.lang.builderの章, Kivy言語の利用(外部ファイル) の章追加
  • 2020/08/14 Module: kivy.uix.buttonの章, Module: kivy.uix.textinputを利用して足し算アプリ作成 の章, 設定を行う機能 の章, スクリーンマネジャー(画面切替) の章追加

著者: NM Max

Created: 2020-08-14 金 19:25

Validate

カテゴリーKivy

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です