kivyAan de slag met Kivy


Opmerkingen

Kivy is een open source Python-bibliotheek voor de snelle ontwikkeling van platformonafhankelijke gebruikersinterfaces. Kivy-applicaties kunnen met dezelfde codebase worden ontwikkeld voor Linux, Windows, OS X, Android en iOS.

Afbeeldingen worden weergegeven via OpenGL ES 2 in plaats van via native widgets, wat leidt tot een redelijk uniform uiterlijk in besturingssystemen.

Het ontwikkelen van interfaces in Kivy omvat optioneel het gebruik van kvlang, een kleine taal die python-achtige uitdrukkingen en python-interop ondersteunt. Het gebruik van kvlang kan de ontwikkeling van een gebruikersinterface drastisch vereenvoudigen in vergelijking met het uitsluitend gebruiken van Python.

Kivy is gratis te gebruiken (momenteel onder de MIT-licentie) en wordt professioneel ondersteund.

Installatie & Setup

ramen

Er zijn twee opties om Kivy te installeren:

Zorg eerst dat de python-tools up-to-date zijn.

python -m pip install --upgrade pip wheel setuptools
 

Installeer vervolgens de basisafhankelijkheden.

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

Hoewel Kivy al providers voor audio en video heeft, is GStreamer vereist voor meer geavanceerde dingen.

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

Om het eenvoudiger te maken, betekent <python> in de volgende tekst een pad naar de map met het bestand python.exe .

  1. Wiel

    Het cython biedt gecompileerde Kivy, maar met verwijderde cython -broncomponenten, wat betekent dat de kerncode op deze manier niet opnieuw kan worden gecompileerd. Python-code kan echter worden bewerkt.

    De stabiele versie van Kivy is beschikbaar op pypi.

    python -m pip install kivy
     

    De nieuwste versie van de officiële repository is beschikbaar via nachtelijk gebouwde wielen die beschikbaar zijn op Google Drive. Ga naar de link in documenten die overeenkomen met uw python-versie. Nadat een geschikt wiel is gedownload, hernoemt u dit om aan de opmaak van dit voorbeeld te voldoen en voert u de opdracht uit.

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

    Er zijn meer vereiste afhankelijkheden nodig om Kivy vanaf de bron te installeren dan met behulp van de wielen, maar de installatie is flexibeler.

    Maak een nieuw bestand in <python>\Lib\distutils\distutils.cfg met deze regels om ervoor te zorgen dat een juiste compiler voor de broncode wordt gebruikt.

    [build]
    compiler = mingw32
     

    Dan is de compiler nodig. Gebruik een aantal dat u al hebt geïnstalleerd of download mingwpy . De belangrijke bestanden zoals gcc.exe bevinden zich in <python>\Scripts .

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

    Vergeet niet om omgevingsvariabelen in te stellen om Kivy te laten weten welke providers het moet gebruiken.

    set USE_SDL2=1
    set USE_GSTREAMER=1
     

    Installeer nu de extra afhankelijkheden die nodig zijn voor de compilatie.

    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/
     

    Controleer het gedeelte Paths om te controleren of alles goed is ingesteld en installeer Kivy. Kies een van deze opties:

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

Paths

Kivy heeft toegang nodig tot de binaire bestanden vanuit sommige afhankelijkheden. Dit betekent dat de juiste mappen moeten worden op het milieu van de PATH variabele.

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

Op deze manier kan Python IDLE IDE worden opgenomen in het pad met <python>\Lib\idlelib; . Schrijf vervolgens idle in de console en IDLE is klaar om Kivy te gebruiken.

Vereenvoudig het

Om herhaling van omgevingsvariabelen te voorkomen, stelt u elk noodzakelijk pad op deze manier in of maakt u een batchbestand ( .bat ) met deze regels in <python> :

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

Om Kivy-project na de installatie uit te voeren, voert u cmd.exe of het batchbestand uit en gebruikt u python <filename>.py

installatie op Ubuntu

Voor het installeren van kivy op ubuntu met kivy opent u bijvoorbeeld terminal en voert u de volgende opdracht uit

Voeg eerst ppa toe

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

Voor kivy installeren

 sudo apt-get install python-kivy
 

Voor kivy-voorbeelden installeren

 sudo apt-get install python-kivy-example
 

Verschillende manieren om een eenvoudige app uit te voeren en om te werken met widgets

De meeste kivy-apps beginnen met deze structuur:

from kivy.app import App

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

Er zijn verschillende manieren om vanaf hier te gaan:

Alle onderstaande codes (behalve voorbeeld 1 en 3) hebben dezelfde widget en vergelijkbare functies, maar tonen een andere manier om de app te bouwen.

Voorbeeld 1: een enkele widget retourneren (eenvoudige 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()
 

Voorbeeld 2: meerdere widgets retourneren + de knop drukt de tekst van het label af

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

Voorbeeld 3: gebruik een klasse (enkele widget) + de knop drukt "Mijn knop" af

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

Voorbeeld 4: het is hetzelfde als ex. 2 maar het laat zien hoe een klasse te gebruiken

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

Met .kv-taal

Voorbeeld 5: hetzelfde, maar laat zien hoe kv-taal in python te gebruiken

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

** Voorbeeld 6: hetzelfde met het kv gedeelte in een Tutorial.kv bestand **

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)
 

** Voorbeeld 7: link naar specifiek kv-bestand + een def in python die het label.text ontvangt **

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: orientatie: "verticaal" Label: id: mylabel tekst: "My App" Knop: tekst: "Click me!" on_press: root.printMe (mylabel.text)

Voorbeeld 8: de knop drukt de tekst van het label af (met een def in python met behulp van ids (de "ID's"))

Let erop dat:

  • self_xx uit voorbeeld 7 wordt vervangen door 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()
 

Voorbeeld 9: de knop drukt de tekst van het label af (met een def in python met 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()
 

Voorbeeld 10: de knop drukt de tekst van het label af (met een def in python met 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 wereld in Kivy.

De volgende code illustreert hoe je 'hallo wereld' app in Kivy maakt. Om deze app in iOS en Android uit te voeren, moet je deze opslaan als main.py en buildozer gebruiken.

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

Eenvoudig pop-upvoorbeeld in Kivy.

De volgende code illustreert hoe u een eenvoudige pop-up maakt met 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()
 

Aanraken, grijpen en bewegen

In het volgende voorbeeld wordt een canvas gemaakt met 2 punten en 1 lijn ertussen. U kunt het punt en de lijn verplaatsen.

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