Einstieg in Kivy (GUI)¶
Es gibt mehrere Möglichkeiten, für dein Python-Programm eine graphische Oberfläche (GUI - Graphical User Interface) zu programmieren. Im Folgenden beschreibe ich Kivy, wessen Apps auf allen gängigen Betriebssystemen und Handys laufen können. Auf Android gibt's den Kivy-Launcher, mit dem man die Dateien direkt auf dem Handy ausführen kann. Und in den Kivy-Downloads findet man eine VirtualBox-Maschine, auf der Buildozer vorinstalliert ist, um damit apk-Dateien zu erstellen.
Hallo-Welt¶
Das Hallo-Welt-Programm auf der Kivy-Homepage sieht so aus:
```python
!/usr/bin/env python3¶
from kivy.app import App from kivy.uix.button import Button
class TestApp(App): def build(self): return Button(text='Hallo Welt')
TestApp().run() ```
Wie du von der Programmierung von Internetseiten bereits weißt, hat es Vorteile, den Inhalt von der Form zu trennen. Dem HTML-Code entspricht hier der Python-Code in einer Datei der Form *.py
, und dem CSS-Code der Kivy-Code in einer Datei der Form *.kv
.
Das Hallo-Welt-Programm sieht dann so aus: In der py-Datei steht:
```python
!/usr/bin/env python3¶
import kivy from kivy.app import App
class HalloApp(App): pass
if name == 'main':
HalloApp().run()
``
Und in der Datei
hallo.kv` steht:
python
Button:
text: 'Hallo Welt'
Damit das funktioniert, muss der Dateiname der kv-Datei so heißen wie das Wort vor "App" in der py-Datei.
Widgets und ihr Layout¶
Will man in einem Fenster etwas erscheinen lassen, spricht man davon, ein Widget hinzuzufügen. Jedes Programm hat ein root widget, dem du Kinder-Widgets hinzufügen kannst. Die Zugehörigkeiten der Widgets zueinander kann man in einem hierarchischen Baumdiagramm aufzeichnen. Abhängig davon wie die Kinder-Widgets angeordnet sein sollen, entscheidest du dich für ein Layout (1, 2). Im Folgenden wird das BoxLayout verwendet, damit alle Widgets schön untereinander sind. Im KivyCatalog (1 , 2) kann man die verschiedenen Layouts ausprobieren.
Das Hallo-Welt-Programm kann dann so aussehen:
kivy_hallo_welt_3.py ```python
!/usr/bin/env python3¶
import kivy from kivy.app import App from kivy.uix.boxlayout import BoxLayout
class WurzelWidget(BoxLayout): pass
class HalloWidgetApp(App): def build(self): return WurzelWidget()
if name == 'main':
HalloWidgetApp().run()
hallowidget.kv
python
Übergabe von Objekten zwischen Python- und Kivy-Code¶
Um eine Aktion des Anwenders deines Programms in deinem Python-Code verarbeiten zu können, muss dein Python-Code auf die Widgets in deinem Kivy-Code zugreifen können. Wenn der Anwender z.B. auf einen Button klickt, soll der Python-Code etwas tun.
Zugriff auf Text kann man auf mehreren Wegen kriegen. Um einer Funktion funktion(self, etwas)
etwas aus einem Widget zu übergeben, verwendet man bei einem Event root.funktion(etwas)
. Will man wiederum einen damit kreierten Output in einem Widget anzeigen, muss man entweder eine StringProperty()
definieren oder den Output dem Widget über seine id
zuweisen. Aus dem folgenden Beispiel kannst du beide Methoden ablesen. (Du solltest allerdings nicht beide Methoden vermischen, sonst funktioniert das was du willst vielleicht nur bei der ersten Ausführung, da die Variable mit einem konkreten Wert überschrieben wird.)
kivy_widget-access.py: ```python
!/usr/bin/env python3¶
import kivy from kivy.app import App from kivy.uix.boxlayout import BoxLayout from kivy.properties import StringProperty
class Login(BoxLayout): outpt = StringProperty('Fülle bitte beide Felder aus.') # 1. Weg: Um durch access_widget_1 den text des Labels zu ändern, wird hier eine Variable definiert, auf die der Python- und Kivy-Code dieser Klasse ("Plugin") Zugriff haben.
1 2 3 4 5 6 7 |
|
class WidgetAccessApp(App): def build(self): return Login()
if name == 'main': WidgetAccessApp().run() ```
widgetaccess.kv:
```python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
|
```
Bemerkungen zu self, root und app:
Verwendet man eine Variable, muss man sagen, wo sie verwaltet wird. Das outpt
und die Widget-IDs sind im Mutter-Widget Login
definiert. Will man in der Funktion access_widget_1
darauf zugreifen, muss man das mit self
tun, weil das aktuelle Widget beim Ausführen der Funktion das Widget Login
ist. Im Kivy-Code muss man hingegen mit root
darauf zugreifen, weil self
das Label-Widget wäre und man auf die erste Instanz in der Hierarchie schauen muss. Definiert man in der App-Klasse (hier WidgetAccessApp(App)
) etwas, auf das man im Kivy-Code zugreifen will (z.B. def funktion(self)
), dann macht man das mit app.funktion()
. Mehr zu Werten von Properties.
Um auf andere Dinge als Text zuzugreifen, z.B. auf den Zustand eines Buttons, ob er gerade gedrückt ist oder nicht, verwendet man andere Properties wie ObjectProperty
, ListProperty
oder RecycleView
. Mehr zu Properties
Aufgaben¶
EA: BMI-Rechner¶
Erweitere deinen BMI-Rechner zu einer App mit graphischer Oberfläche.
EA: Verschlüsselung¶
Informiere dich auf cryptool-online über Techniken, einen Text zu verschlüsseln und programmiere dein eigenes Verschlüsselungsprogramm. Deine Grundstruktur könnte wie folgt aussehen.
verschluesselung.py: ```python
!/usr/bin/env python3¶
import kivy from kivy.app import App from kivy.uix.boxlayout import BoxLayout from kivy.properties import StringProperty
from kivy.core.window import Window¶
class Verschluesselung(BoxLayout): ausgabe = StringProperty('Es ist noch kein Text zum Übersitzen eingegeben.')
1 2 |
|
class VerschluesselungsappApp(App): def build(self): kivy.Config.set('graphics', 'width', 900) kivy.Config.set('graphics', 'height', 600) # Window.fullscreen = True return Verschluesselung()
if name == 'main': VerschluesselungsappApp().run() ```
verschluesselungsapp.kv:
```python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
```
EA: Vertiefung¶
Um eine App mit mehreren Fenstern zu programmieren, bietet sich der Screen Manager an.
Weitere Möglichkeiten von Python und Kivy erfährst du, wenn du die Examples studierst.
Hilfe kannst du dir bei stackoverflow.com holen.
Willst du Module/Packages verwenden, die im Kivy Launcher nicht vorhanden sind, verwendest du am besten QPython und installierst damit über pip dein Module.