====== Appunti Kivy ======
===== Python Code and KV Language =====
This is the **kivyexample.py** file:
#!/usr/bin/env python
from kivy.app import App
#kivy.require("1.8.0")
from kivy.uix.floatlayout import FloatLayout
class MyLayout(FloatLayout):
pass
class KivyExampleApp(App):
def build(self):
return MyLayout()
if __name__ == "__main__":
KivyExampleApp().run()
In the code above we derived a class named **KivyExampleApp** from the Kivy's **App** class. The Kivy code will automatically search for a file called **kivyexample.kv**, and it will parse it using the **KV language**. The name of the file is derived by the class name, making it all lowercase and removing the leftmost **//App//** part (if it exists). So this is the **kivyexample.kv** file:
:
font_size: 40
color: 0,1,0,1
size_hint: 0.3, 0.2
:
MyButton:
text: "Pos 0, 0"
pos_hint: {'x': 0, 'y': 0}
MyButton:
text: "Center x-y"
pos_hint: {'center_x': 0.5, 'center_y': 0.5}
MyButton:
text: "Pos right-top"
pos_hint: {'right': 0.9, 'top': 0.3}
MyButton:
text: "Pos 0.5, 1.0"
pos_hint: {'right': 0.5, 'top': 1.0}
In the Python code, the App constructor will return the **MyLayout** class, which is derived from the Kivy's **FloatLayout** class. The original class is an empty widget, but we added several buttons using the KV language.
Notice that **MyLayout** is derived from **FloatLayout** declaring it into the **Python code**, whereas the **MyButton** class is derived from the original **Button** class using the KV language, via the //@Button// construct. The result should be something like this:
{{.:kivy:kivyexample.png?direct&300|KivyExampleApp}}
We used a KV file to define the graphic interface of our App, but **it is possible to do that using only Python code**, thus having only a single file. But doing as seen above has several advantages. First of all you can try to keep the **graphical presentation** and the **code logic** as much **separate** as possibile. Another advantage is that resizing the app's window, will resize all its contents automatically (if you are smart enough not to use absolute values); otherwise you have to bind the window-resize event to a function which should adjust each widget size and position.
===== Using the Widget Class =====
In general our App will return a class derived from the more generic **Widget** class, not the //FloatLayout// or others layouts classes. So the KV file will look like this:
:
FloatLayout:
size: root.size
MyButton:
text: "Pos 0, 0"
pos_hint: {'x': 0, 'y': 0}
We requested that the FloatLayout expands to all the parent (root) **size**, so the example will give the same output as in the previous paragraph.
===== A Real App With an ActionBar =====
**kivywindowexample.py**
#!/usr/bin/env python
from kivy.app import App
#kivy.require("1.8.0")
from kivy.uix.widget import Widget
class MyWidget(Widget):
pass
class KivyWindowExampleApp(App):
def build(self):
return MyWidget()
if __name__ == "__main__":
KivyWindowExampleApp().run()
**kivywindowexample.kv**
:
font_size: 28
color: 0,1,0,1
size_hint: 0.3, 0.2
:
BoxLayout:
size: root.size
orientation: 'vertical'
ActionBar:
pos_hint: {'top': 1}
ActionView:
use_separator: True
ActionPrevious:
title: "MyGame"
with_previous: False
ActionOverflow:
ActionButton:
text: "Exit"
ActionButton:
text: "About"
ActionButton:
text: "New Game"
FloatLayout:
MyButton:
text: "Pos 0, 0"
pos_hint: {'x': 0, 'y': 0}
MyButton:
text: "Center x-y"
pos_hint: {'center_x': 0.5, 'center_y': 0.5}
MyButton:
text: "Pos right-top"
pos_hint: {'right': 0.9, 'top': 0.3}
MyButton:
text: "Pos 0.5, 1.0"
pos_hint: {'right': 0.5, 'top': 1.0}
{{.:kivy:kivywindowexample.png?direct&320|Kivy ActionBar Example}}
===== Logging =====
Like a plain Python program, it is possible for a Kivy app to produce some logging using the Kivy logger. The output will go, by default, to a file created into the app home directory, into the **files/app/.kivy/logs/** directory.
from kivy.logger import Logger, LOG_LEVELS
# Set the loglevel. The Android log file will be create into
# [app_home]/files/app/.kivy/logs/
Logger.setLevel(LOG_LEVELS['debug'])
Logger.info('Informative message')
Without root privileges it is not possibile for another Android app (e.g. a file browser) to access the log directory. The Kivy **app home** will be into the adopted SD card, under something like this:
/mnt/expand/[UUID]/user/0/[fully.qualified.app.name]
In older Android versions (e.g. Android 8) the app home directory will be something like:
/data/data/[fully.qualified.app.name]
Every time that the Kivy environment is initializated, a new log file will be created; the filename will be something like **kivy_YY-MM-DD_N.txt**, where YY-MM-DD is the date and N is a progressive integer starting from zero.