kivyKivyを使い始める


備考

Kivyは、クロスプラットフォームのユーザインタフェースを迅速に開発するためのオープンソースのPythonライブラリです。 Kivyアプリケーションは、同じコードベースを使用して、Linux、Windows、OS X、Android、およびiOS向けに開発することができます。

グラフィックスは、ネイティブウィジェットではなく、OpenGL ES 2でレンダリングされるため、オペレーティングシステム間でかなり均一な外観になります。

Kivyのインターフェイスを開発するには、オプションで、Pythonのような式とPythonの相互運用をサポートする小さな言語のkvlangを使用する必要があります。 kvlangを使用すると、Pythonを独占的に使用するのに比べて、ユーザインタフェースの開発を大幅に簡素化できます。

Kivyは現在(MITライセンスの下で)自由に使用でき、専門的にサポートしています。

インストールとセットアップ

Windows

Kivyをインストールするには2つの方法があります:

最初に、Pythonツールが最新であることを確認します。

python -m pip install --upgrade pip wheel setuptools
 

次に、基本的な依存関係をインストールします。

python -m pip install docutils pygments pypiwin32 kivy.deps.sdl2 kivy.deps.glew
 

Kivyには既にオーディオとビデオのプロバイダがありますが、より高度なものにはGStreamerが必要です。

python -m pip install kivy.deps.gstreamer --extra-index-url https://kivy.org/downloads/packages/simple/
 

簡単にするために、次のテキストの<python> は、 python.exe ファイルを含むディレクトリへのパスを意味します。

  1. ホイール

    ホイールパッケージはコンパイルされたKivyを提供しますが、削除されたcython ソースコンポーネントがあるため、コアコードをこの方法で再コンパイルすることはできません。ただし、Pythonコードは編集可能です。

    安定版のKivyはpypiで利用できます。

    python -m pip install kivy
     

    公式レポジトリの最新バージョンは、Googleドライブで使用可能な夜間車輪を介して入手できます。あなたのpythonのバージョンに一致するドキュメントのリンクにアクセスしてください。適切なホイールがダウンロードされたら、この例のフォーマットに合うように名前を変更し、コマンドを実行します。

    python -m pip install C:\Kivy-1.9.1.dev-cp27-none-win_amd64.whl
     
  2. ソース

    車輪を使用するよりもKivyをソースからインストールするために必要な依存関係がさらに必要ですが、インストールはより柔軟です。

    <python>\Lib\distutils\distutils.cfg 新しいファイルを作成し、ソースコードに適切なコンパイラが使用されるようにします。

    [build]
    compiler = mingw32
     

    コンパイラが必要です。すでにインストールされているものを使用するか、 mingwpy ダウンロードしてmingwpygcc.exe ような重要なファイルは<python>\Scripts ます。

    python -m pip install -i https://pypi.anaconda.org/carlkl/simple mingwpy
     

    環境変数を設定してKivyに使用するプロバイダを知らせるようにしてください。

    set USE_SDL2=1
    set USE_GSTREAMER=1
     

    コンパイルに必要な追加の依存関係をインストールします。

    python -m pip install cython kivy.deps.glew_dev kivy.deps.sdl2_dev
    python -m pip install kivy.deps.gstreamer_dev --extra-index-url https://kivy.org/downloads/packages/simple/
     

    すべてのPaths が正しく設定されていることを確認し、Kivyをインストールしてください。次のいずれかのオプションを選択します。

    python -m pip install C:\master.zip
    python -m pip install https://github.com/kivy/kivy/archive/master.zip
     

パス

Kivyはいくつかの依存関係からバイナリにアクセスする必要があります。つまり、正しいフォルダ環境のPATH 変数になければなりません。

set PATH=<python>\Tools;<python>\Scripts;<python>\share\sdl2\bin;%PATH%
 

このようにして、Python IDLE IDEを<python>\Lib\idlelib; パスに含めることができます<python>\Lib\idlelib; 。次に、 idle をコンソールに書き込むと、IDLEはKivyを使用できる状態になります。

それを簡略化する

環境変数を繰り返し設定するのを避けるには、必要なパスをこのように設定するか、バッチ( .bat )ファイルを<python> 配置します。

set PATH=%~dp0;%~dp0Tools;%~dp0Scripts;%~dp0share\sdl2\bin;%~dp0Lib\idlelib;%PATH%
cmd.exe
 

インストール後にKivyプロジェクトを実行するには、 cmd.exe またはバッチファイルを実行し、 python <filename>.py を使用しpython <filename>.py

Ubuntuにインストール

Kivyのopen terminalを使ってubuntuをインストールし、次のコマンドを実行するには

最初にppaを追加する

 sudo add-apt-repository ppa:kivy-team/kivy
 

インストールkivyの場合

 sudo apt-get install python-kivy
 

Kivyのインストール例

 sudo apt-get install python-kivy-example
 

シンプルなアプリケーションを実行してウィジェットとやりとりするさまざまな方法

ほとんどのkivyアプリはこの構造から始まります:

from kivy.app import App

class TutorialApp(App):
    def build(self):
        return 
TutorialApp().run()
 

ここからいくつかの方法があります:

下のすべてのコード(例1と3を除く)は同じウィジェットと同様の機能を持ちますが、アプリを構築する方法は異なります。

例1:単一のウィジェット(単純なHello Worldアプリケーション)を返す

from kivy.app import App
from kivy.uix.button import Button
class TutorialApp(App):
    def build(self):
        return Button(text="Hello World!")
TutorialApp().run()
 

例2:いくつかのウィジェットを返す+ボタンがラベルのテキストを出力する

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.button import Button

class TutorialApp(App):
    def build(self):
        mylayout = BoxLayout(orientation="vertical")
        mylabel = Label(text= "My App")
        mybutton =Button(text="Click me!")  
        mylayout.add_widget(mylabel)
        mybutton.bind(on_press= lambda a:print(mylabel.text))
        mylayout.add_widget(mybutton)
        return mylayout
TutorialApp().run()
 

例3:クラス(単一のウィジェット)を使用する+ボタンは "My Button"

from kivy.app import App
from kivy.uix.button import Button

class Mybutton(Button):
    text="Click me!"
    on_press =lambda a : print("My Button")    
    
class TutorialApp(App):
    def build(self):
        return Mybutton()
TutorialApp().run()
 

例4:exと同じです。 2しかしそれはクラスを使用する方法を示します

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.button import Button

class MyLayout(BoxLayout):
    #You don't need to understand these 2 lines to make it work!
    def __init__(self, **kwargs):
        super(MyLayout, self).__init__(**kwargs)
        
        self.orientation="vertical"
        mylabel = Label(text= "My App")
        self.add_widget(mylabel)
        mybutton =Button(text="Click me!")
        mybutton.bind(on_press= lambda a:print(mylabel.text))
        self.add_widget(mybutton)
        
class TutorialApp(App):
    def build(self):
        return MyLayout()
TutorialApp().run()
 

.kv言語で

例5:同じですが、pythonの KV言語を使用する方法を示します

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout 
# BoxLayout: it's in the python part, so you need to import it

from kivy.lang import Builder
Builder.load_string("""
<MyLayout>
    orientation:"vertical"
    Label: # it's in the kv part, so no need to import it
        id:mylabel
        text:"My App"
    Button:
        text: "Click me!"
        on_press: print(mylabel.text)
""")
class MyLayout(BoxLayout):
    pass
class TutorialApp(App):
    def build(self):
        return MyLayout()
TutorialApp().run()
 

**例6: Tutorial.kv ファイルのkv 部分と同じ**

.pyでは:

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout

class MyLayout(BoxLayout):
    pass
class TutorialApp(App):  
#the kv file name will be Tutorial (name is before the "App")
    def build(self):
        return MyLayout()
TutorialApp().run()
 

Tutorial.kvで:

<MyLayout> # no need to import stuff in kv!
    orientation:"vertical"
    Label:
        id:mylabel
        text:"My App"
    Button:
        text: "Click me!"
        on_press: print(mylabel.text)
 

**例7:特定のkvファイルへのリンク+ label.textを受け取るpythonのdef **

.pyでは:

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout

class MyLayout(BoxLayout):
    def printMe(self_xx, yy):
        print(yy)
class TutorialApp(App): 
    def build(self):
        self.load_kv('myapp.kv')
        return MyLayout()
TutorialApp().run()
 

myapp.kv:orientation: "vertical"ラベル:id:mylabelテキスト: "My App"ボタン:テキスト: "Click me!" on_press:root.printMe(mylabel.text)

例8:ボタンはラベルのテキストを印刷します( ids ( "IDs")を使用してPythonでdefを使用)

注意:

  • 例7のself_xxself 置き換えられました

.pyでは:

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout

class MyLayout(BoxLayout):
    def printMe(self):
        print(self.ids.mylabel.text)
class TutorialApp(App):
    def build(self):
        self.load_kv('myapp.kv')
        return MyLayout()
TutorialApp().run()
 

myapp.kv:

<MyLayout>
    orientation:"vertical"
    Label:
        id:mylabel
        text:"My App"
    Button:
        text: "Click me!"
        on_press: root.printMe()
 

例9:ボタンはラベルのテキストを出力します(StringPropertyを使用してPythonでdefを使用)

.pyでは:

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import StringProperty
class MyLayout(BoxLayout):
    stringProperty_mylabel= StringProperty("My App")
    def printMe(self):
        print(self.stringProperty_mylabel)

class TutorialApp(App):
    def build(self):
        return MyLayout()
TutorialApp().run()
 

Tutorial.kvで:

<MyLayout>
    orientation:"vertical"
    Label:
        id:mylabel
        text:root.stringProperty_mylabel
    Button:
        text: "Click me!"
        on_press: root.printMe()
 

例10:ボタンはラベルのテキストを印刷します(ObjectPropertyを使用してPythonでdefを使用)

.pyでは:

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ObjectProperty
class MyLayout(BoxLayout):
    objectProperty_mylabel= ObjectProperty(None)
    def printMe(self):
        print(self.objectProperty_mylabel.text)

class TutorialApp(App):
    def build(self):
        return MyLayout()
TutorialApp().run()
 

Tutorial.kvで:

<MyLayout>
    orientation:"vertical"
    objectProperty_mylabel:mylabel
    Label:
        id:mylabel
        text:"My App"
    Button:
        text: "Click me!"
        on_press: root.printMe()
 

こんにちはkivyの世界。

次のコードは、iOSとAndroidでこのアプリケーションを実行するには、main.pyとして保存し、buildozerを使用します。

from kivy.app import App
from kivy.uix.label import Label
from kivy.lang import Builder

Builder.load_string('''
<SimpleLabel>:
    text: 'Hello World'
''')


class SimpleLabel(Label):
    pass


class SampleApp(App):
    def build(self):
        return SimpleLabel()

if __name__ == "__main__":
    SampleApp().run()
 

RecycleView

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.button import Button


items = [
    {"color":(1, 1, 1, 1), "font_size": "20sp", "text": "white",     "input_data": ["some","random","data"]},
    {"color":(.5,1, 1, 1), "font_size": "30sp", "text": "lightblue", "input_data": [1,6,3]},
    {"color":(.5,.5,1, 1), "font_size": "40sp", "text": "blue",      "input_data": [64,16,9]},
    {"color":(.5,.5,.5,1), "font_size": "70sp", "text": "gray",      "input_data": [8766,13,6]},
    {"color":(1,.5,.5, 1), "font_size": "60sp", "text": "orange",    "input_data": [9,4,6]},
    {"color":(1, 1,.5, 1), "font_size": "50sp", "text": "yellow",    "input_data": [852,958,123]}
]


class MyButton(Button):

    def print_data(self,data):
        print(data)


KV = '''

<MyButton>:
    on_release:
        root.print_data(self.input_data)

RecycleView:
    data: []
    viewclass: 'MyButton'
    RecycleBoxLayout:
        default_size_hint: 1, None
        orientation: 'vertical'

'''


class Test(App):
    def build(self):
        root = Builder.load_string(KV)
        root.data = [item for item in items]
        return root


Test().run()
 

Kivyの簡単なポップアップの例

次のコードは、Kivyで単純なポップアップを行う方法を示しています。

from kivy.app import App
from kivy.uix.popup import Popup
from kivy.lang import Builder
from kivy.uix.button import Button

Builder.load_string('''
<SimpleButton>:
    on_press: self.fire_popup()
<SimplePopup>:
    id:pop
    size_hint: .4, .4
    auto_dismiss: False
    title: 'Hello world!!'
    Button:
        text: 'Click here to dismiss'
        on_press: pop.dismiss()
''')


class SimplePopup(Popup):
    pass

class SimpleButton(Button):
    text = "Fire Popup !"
    def fire_popup(self):
        pops=SimplePopup()
        pops.open()

class SampleApp(App):
    def build(self):
        return SimpleButton()

SampleApp().run()
 

タッチ、グラブ、移動

次の例では、2点と1行の間にキャンバスを作成します。ポイントとラインを動かすことができます。

from kivy.app import App
from kivy.graphics import Ellipse, Line
from kivy.uix.boxlayout import BoxLayout


class CustomLayout(BoxLayout):

    def __init__(self, **kwargs):
        super(CustomLayout, self).__init__(**kwargs)

        self.canvas_edge = {}
        self.canvas_nodes = {}
        self.nodesize = [25, 25]

        self.grabbed = {}

        #declare a canvas
        with self.canvas.after:
            pass

        self.define_nodes()
        self.canvas.add(self.canvas_nodes[0])
        self.canvas.add(self.canvas_nodes[1])
        self.define_edge()
        self.canvas.add(self.canvas_edge)
    

    def define_nodes(self):
        """define all the node canvas elements as a list"""

        self.canvas_nodes[0] = Ellipse(
            size = self.nodesize,
            pos =  [100,100]
            )

        self.canvas_nodes[1] = Ellipse(
            size = self.nodesize,
            pos =  [200,200]
            )

    def define_edge(self):
        """define an edge canvas elements"""


        self.canvas_edge = Line(
            points =  [
                self.canvas_nodes[0].pos[0] + self.nodesize[0] / 2,
                self.canvas_nodes[0].pos[1] + self.nodesize[1] / 2,
                self.canvas_nodes[1].pos[0] + self.nodesize[0] / 2,
                self.canvas_nodes[1].pos[1] + self.nodesize[1] / 2
                ],
            joint = 'round',
            cap = 'round',
            width = 3
            )


    def on_touch_down(self, touch):

        for key, value in self.canvas_nodes.items():
            if (value.pos[0] - self.nodesize[0]) <= touch.pos[0] <= (value.pos[0] + self.nodesize[0]):
                if (value.pos[1] - self.nodesize[1]) <= touch.pos[1] <= (value.pos[1] + self.nodesize[1]):
                    touch.grab(self)
                    self.grabbed = self.canvas_nodes[key]
                    return True

    def on_touch_move(self, touch):

        if touch.grab_current is self:
            self.grabbed.pos = [touch.pos[0] - self.nodesize[0] / 2, touch.pos[1] - self.nodesize[1] / 2]
            self.canvas.clear()
            self.canvas.add(self.canvas_nodes[0])
            self.canvas.add(self.canvas_nodes[1])
            self.define_edge()
            self.canvas.add(self.canvas_edge)
        else:
            # it's a normal touch
            pass

    def on_touch_up(self, touch):
        if touch.grab_current is self:
            # I receive my grabbed touch, I must ungrab it!
            touch.ungrab(self)
        else:
            # it's a normal touch
            pass

class MainApp(App):

    def build(self):
        root = CustomLayout()
        return root

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