kivyErste Schritte mit Kivy


Bemerkungen

Kivy ist eine Open-Source-Python-Bibliothek für die schnelle Entwicklung plattformübergreifender Benutzeroberflächen. Kivy-Anwendungen können für Linux, Windows, OS X, Android und iOS mit derselben Codebase entwickelt werden.

Grafiken werden über OpenGL ES 2 und nicht über native Widgets gerendert, was zu einem einheitlichen Erscheinungsbild für alle Betriebssysteme führt.

Für die Entwicklung von Schnittstellen in Kivy ist optional die Verwendung von Kvlang erforderlich, einer kleinen Sprache, die Python-ähnliche Ausdrücke und Python-Interop unterstützt. Die Verwendung von kvlang kann die Entwicklung der Benutzeroberfläche im Vergleich zur ausschließlichen Verwendung von Python erheblich vereinfachen.

Kivy ist kostenlos (derzeit unter der MIT-Lizenz) und professionell abgesichert.

Installation und Einrichtung

Windows

Es gibt zwei Möglichkeiten, Kivy zu installieren:

Stellen Sie zunächst sicher, dass die Python-Tools auf dem neuesten Stand sind.

python -m pip install --upgrade pip wheel setuptools
 

Dann installieren Sie die grundlegenden Abhängigkeiten.

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

Obwohl Kivy bereits Anbieter für Audio & Video hat, ist GStreamer für Fortgeschrittene erforderlich.

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

Zur Vereinfachung bedeutet <python> im folgenden Text einen Pfad zum Verzeichnis mit der Datei python.exe .

  1. Rad

    Das Radpaket enthält kompiliertes Kivy, jedoch mit entfernten cython Quellkomponenten. Dies bedeutet, dass der Kerncode auf diese Weise nicht erneut kompiliert werden kann. Python-Code kann jedoch bearbeitet werden.

    Die stabile Version von Kivy ist auf pypi verfügbar.

    python -m pip install kivy
     

    Die neueste Version aus dem offiziellen Repository ist über nächtlich gebaute Räder erhältlich, die auf Google Drive verfügbar sind. Besuchen Sie den Link in den Dokumenten, die Ihrer Python-Version entsprechen. Benennen Sie das Rad nach dem Herunterladen um, um es der Formatierung dieses Beispiels anzupassen, und führen Sie den Befehl aus.

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

    Für die Installation von Kivy von der Quelle aus sind mehr Abhängigkeiten erforderlich als für die Verwendung der Laufräder. Die Installation ist jedoch flexibler.

    Erstellen Sie eine neue Datei in <python>\Lib\distutils\distutils.cfg mit diesen Zeilen, um sicherzustellen, dass ein geeigneter Compiler für den Quellcode verwendet wird.

    [build]
    compiler = mingw32
     

    Dann wird der Compiler benötigt. Verwenden Sie entweder bereits installierte oder laden Sie mingwpy herunter. Die wichtigen Dateien wie gcc.exe befinden sich unter <python>\Scripts .

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

    Vergessen Sie nicht, Umgebungsvariablen festzulegen, damit Kivy wissen kann, welche Anbieter verwendet werden sollen.

    set USE_SDL2=1
    set USE_GSTREAMER=1
     

    Installieren Sie nun die zusätzlichen Abhängigkeiten, die für die Kompilierung erforderlich sind.

    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/
     

    Überprüfen Sie den Abschnitt " Paths ", um sicherzustellen, dass alles richtig eingestellt ist, und installieren Sie Kivy. Wählen Sie eine dieser Optionen:

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

Pfade

Kivy benötigt aus einigen Abhängigkeiten einen Zugriff auf die Binärdateien. Dies bedeutet, dass sich die richtigen Ordner in der PATH Variablen der Umgebung befinden müssen.

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

Auf diese Weise kann Python IDLE IDE mit <python>\Lib\idlelib; in den Pfad <python>\Lib\idlelib; . Dann schreiben Sie idle in die Konsole und IDLE kann Kivy verwenden.

Vereinfachen Sie es

Um ein wiederholtes Setzen von Umgebungsvariablen zu vermeiden, legen Sie entweder jeden erforderlichen Pfad auf diese Weise fest oder erstellen Sie eine Batchdatei ( .bat ) mit diesen Zeilen in <python> :

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

Um Kivy-Projekt nach der Installation auszuführen, führen Sie cmd.exe oder die Batchdatei aus und verwenden Sie python <filename>.py

Installation auf Ubuntu

Für die Installation von kivy auf Ubuntu mit kivy Beispiel öffnen Sie das Terminal und führen Sie den folgenden Befehl aus

Fügen Sie zuerst ppa hinzu

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

Für die Installation von kivy

 sudo apt-get install python-kivy
 

Für die Installation von kivy-Beispielen

 sudo apt-get install python-kivy-example
 

Verschiedene Möglichkeiten, eine einfache App auszuführen und mit Widgets zu interagieren

Die meisten kivy Apps beginnen mit dieser Struktur:

from kivy.app import App

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

Von hier aus gibt es mehrere Möglichkeiten:

Alle nachstehenden Codes (außer Beispiel 1 und 3) weisen dasselbe Widget und ähnliche Funktionen auf, zeigen jedoch eine andere Methode zum Erstellen der App.

Beispiel 1: Rückgabe eines einzelnen Widgets (einfache Hello World App)

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

Beispiel 2: Mehrere Widgets zurückgeben + Die Schaltfläche druckt den Text der Beschriftung

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()
 

Beispiel 3: Verwenden einer Klasse (einzelnes Widget) + die Schaltfläche druckt "Meine Schaltfläche"

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()
 

Beispiel 4: Es ist das gleiche wie bei ex. 2 aber es zeigt, wie man eine Klasse benutzt

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()
 

Mit der .kv-Sprache

Beispiel 5: dasselbe wie die Verwendung der kv-Sprache in Python

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()
 

** Beispiel 6: Dasselbe gilt für den kv Teil in einer Tutorial.kv Datei. **

In .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()
 

In 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)
 

** Beispiel 7: Link zu einer bestimmten kv-Datei + ein Def in Python, der das Label.text empfängt **

In .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()
 

In myapp.kv: Orientierung: "vertikal" Label: id: mylabel text: "My App" Button: text: "Click me!" on_press: root.printMe (mylabel.text)

Beispiel 8: Die Schaltfläche druckt den Text der Beschriftung (mit einem Def in Python mit ids (die "IDs")).

Beachte das:

  • self_xx aus Beispiel 7 wird durch self

In .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()
 

In myapp.kv:

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

Beispiel 9: Die Schaltfläche druckt den Beschriftungstext (mit einem Def in Python mit StringProperty).

In .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()
 

In Tutorial.kv:

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

Beispiel 10: Die Schaltfläche druckt den Beschriftungstext (mit einem Def in Python mit ObjectProperty).

In .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()
 

In Tutorial.kv:

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

Hallo Welt in Kivy.

Der folgende Code veranschaulicht, wie Sie eine Hallo-Welt-App in kivy erstellen können. Um diese App in ios und Android auszuführen, speichern Sie sie als main.py und verwenden Sie 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()
 

Ein einfaches Popup-Beispiel in Kivy.

Der folgende Code veranschaulicht, wie ein einfaches Popup mit Kivy ausgeführt wird.

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()
 

Berühren, greifen und bewegen

Im folgenden Beispiel wird eine Leinwand mit 2 Punkten und 1 Linie dazwischen erstellt. Sie können den Punkt und die Linie verschieben.

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()