Python Kivy

Tutorial 59 of 65 · pythondeck.com Python course

Kivy is a Python framework for cross-platform apps including Android and iOS. Uses its own KV language for declarative UIs and OpenGL-accelerated rendering.

Kivy targets multitouch and novel UIs—games, kiosks, and Raspberry Pi dashboards—with OpenGL-accelerated widgets and KV language for declarative layout.

Python-first mobile experiments (Buildozer) start here though production mobile often shifts to native or Flutter bridges.

The framework predates Material Design—expect to craft custom themes rather than inherit platform-native chrome automatically.

Community examples and Kivy Garden extensions fill gaps for charts, maps, and complex widgets not in core.

App class — build(), lifecycle, Clock scheduling.

KV language — rules bind properties between widgets and Python classes.

Layouts — BoxLayout, GridLayout, FloatLayout; size hints and pos_hint.

Input — multitouch, gestures; collision with desktop mouse events.

Canvas — vector instructions for custom drawing.

Packaging — Buildozer for Android APK; platform-specific deps.

Kivy's strength is custom interaction design, not native OS look-and-feel. Clock.schedule_interval drives animations; default 60fps mindset. For heavy physics, pair with pymunk. Cross-compile Android requires patience with NDK versions and permissions in buildozer.spec.

Desktop Kivy works but exe size and GPU drivers vary—test target hardware early.

Sound and video providers integrate for kiosk experiences; permissions on Android still require manifest edits outside Python.

Pair Kivy with Redis or MQTT on Pi dashboards so UI thread never blocks on sensor polling loops.

Assuming widgets auto-scale like responsive web CSS without size_hint.

Blocking main loop with synchronous network in on_touch handlers.

Underestimating Android packaging debug time (SDK/NDK paths).

Mixing multiple App instances or misusing root widget rules in KV.

Hard-coding pixel sizes that break on high-DPI phones and tablets.

Keep logic in Python classes; KV only for structure and bindings.

Profile GPU draw calls when UI stutters on low-end devices.

Use Clock.create_trigger for debounced resize/layout updates.

Document hardware minimums for kiosk deployments.

Prototype touch targets at 48dp minimum for finger-friendly kiosk layouts.

Re-read the examples below with these ideas in mind; change variable names and inputs to match your own project.

The program below demonstrates hello kivy. Read the comments on each line, run the code, then change names or values to see how the output shifts.

# Example: Hello Kivy
# Run in the REPL or save as a .py file and execute with python.
from kivy.app import App
from kivy.uix.label import Label

class Demo(App):
    def build(self):
        return Label(text="Hello Kivy", font_size=32)

Demo().run()

This sample walks through button in a small, runnable script. Paste it into the REPL or save it as a .py file before you continue to the next block.

# Example: Button
# Run in the REPL or save as a .py file and execute with python.
from kivy.app import App
from kivy.uix.button import Button

class Demo(App):
    def build(self):
        btn = Button(text="Press me")
        btn.bind(on_press=lambda *_: print("pressed"))
        return btn

Demo().run()

Here is a hands-on illustration of kv language. Follow the inline comments first; only then execute the snippet and compare the result with what you expected.

# Example: KV language
# Run in the REPL or save as a .py file and execute with python.
from kivy.app import App
from kivy.lang import Builder

kv = '''
BoxLayout:
    orientation: 'vertical'
    Label:
        text: 'PythonDeck'
    Button:
        text: 'OK'
'''

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

Demo().run()

The program below demonstrates label button. Read the comments on each line, run the code, then change names or values to see how the output shifts.

# Kivy uses kv language or Python for mobile-friendly UIs
from kivy.app import App  # app base
from kivy.uix.boxlayout import BoxLayout  # vertical/horizontal box
from kivy.uix.label import Label  # text display
from kivy.uix.button import Button  # tap target

class Demo(BoxLayout):  # root widget
    def __init__(self, **kw):  # constructor
        super().__init__(orientation="vertical", **kw)  # vertical stack
        self.lbl = Label(text="0")  # counter label
        self.add_widget(self.lbl)  # add to layout
        btn = Button(text="+")  # increment button
        btn.bind(on_press=self.inc)  # event binding
        self.add_widget(btn)  # add button
    def inc(self, *_):  # handler ignores args
        self.lbl.text = str(int(self.lbl.text) + 1)  # bump counter

# Demo().run()  # starts Kivy loop when executed

This sample walks through clock schedule in a small, runnable script. Paste it into the REPL or save it as a .py file before you continue to the next block.

# kivy.clock schedules callbacks on the main thread
from kivy.clock import Clock  # scheduler
ticks = {"n": 0}  # mutable counter

def on_tick(dt):  # dt is delta time seconds
    ticks["n"] += 1  # increment
    print("tick", ticks["n"], "dt", round(dt, 3))  # log
    if ticks["n"] >= 3:  # stop after 3
        return False  # returning False unschedules

event = Clock.schedule_interval(on_tick, 0.2)  # every 0.2s
Clock.schedule_once(lambda dt: event.cancel(), 1.0)  # safety cancel
print("scheduled")  # confirmation

« Python PyQt All tutorials Python Flet »