Book Image

Kivy Blueprints

By : Vasilkov
Book Image

Kivy Blueprints

By: Vasilkov

Overview of this book

This book is intended for programmers who are comfortable with the Python language and who want to build desktop and mobile applications with rich GUI in Python with minimal hassle. Knowledge of Kivy is not strictly required—every aspect of the framework is described when it's first used.
Table of Contents (12 chapters)
10
A. The Python Ecosystem
11
Index

Modern UI

At the time of writing this, the flat design paradigm is trending in the interface design field, systematically taking over every platform, be it Web, mobile, or desktop. Prominent examples of this paradigm shift in the wild are iOS 7 and later and Windows 8 and later. Internet companies followed suit with the "Material design principles" presented at Google I/O 2014 conference, along with many other HTML5 frameworks, including the well-established ones, for example, Bootstrap.

Conveniently, the flat design emphasizes content over presentation, omitting photo-realistic shadows and detailed textures in favor of plain colors and simple geometry. It is by all means simpler to create programmatically than the "old school" skeuomorphic design that tends to be visually rich and artistic.

Note

Skeuomorphism is a common approach to user interface design. It is characterized by applications visually imitating their real-world counterparts, for example, a Calculator app with the same button layout and look and feel as a cheap physical calculator. This may or may not help user experience (depending on who you ask).

Giving up visual details in favor of a simpler, more streamlined interface seems to be the direction everyone is going in today. On the other hand, it's naturally challenging to build a distinctive, memorable interface just from colored rectangles and such. This is why the flat design is typically synonymous with good typography; depending on the application, text is almost always a significant part of the UI, so we want it to look great.

Design inspiration

Imitation is the sincerest form of flattery, and we will imitate the clock design from Android 4.1 Jelly Bean. The distinctive feature of this design is the font weight contrast. Until it was changed in version 4.4 KitKat, the default clock used to look like this:

Design inspiration

Clock in Jelly Bean flavor of Android, as seen on the lock screen.

The font used is Roboto, Google's Android font that superseded the Droid font family in Android 4.0 Ice Cream Sandwich.

Roboto is free for commercial use and available under the permissive Apache License. It can be downloaded from Google Fonts or from the excellent Font Squirrel library at http://www.fontsquirrel.com/fonts/roboto.

Loading custom fonts

When it comes to the typography, Kivy defaults to Droid Sans—Google's earlier font. It's easy to replace Droid with a custom font, as Kivy allows us to specify the font_name property for textual widgets (in this case, Label).

In the simplest case when we have just one font variant, it is possible to assign a .ttf filename directly in the definition of a widget:

Label:
    font_name: 'Lobster.ttf'

For the aforementioned design, however, we want different font weights, so this approach won't cut it. The reason being, every variation of a font (for example, bold or italic) commonly lives in a separate file, and we can only assign one filename to the font_name property.

Our use case, involving more than one .ttf file, is better covered by a LabelBase.register static method. It accepts the following arguments (all optional), exemplified by the Roboto font family:

# In Python code
LabelBase.register(name="Roboto",
    fn_regular="Roboto-Regular.ttf",
    fn_bold="Roboto-Bold.ttf",
    fn_italic="Roboto-Italic.ttf",
    fn_bolditalic="Roboto-BoldItalic.ttf")

After this invocation, it becomes possible to set the font_name property of a widget to the name of the previously registered font family, Roboto in this case.

This approach has two limitations to be aware of:

  • Kivy only accepts TrueType .ttf font files. If the fonts are packaged as OpenType .otf or a web font format such as .woff, you may need to convert them first. This can be easily done using the FontForge editor, which can be found at http://fontforge.org/.
  • There is a maximum of four possible styles per font: normal, italic, bold, and bold italic. It's fine for older font families, such as Droid Sans, but many modern fonts include anywhere from 4 to over 20 styles with varying font weight and other features. Roboto, which we're going to use shortly, is available in at least 12 styles.
Loading custom fonts

The six font weights of Roboto font

The second point forces us to choose which font styles we will use in our application as we can't just throw in all 12, which is a bad idea anyway as it would lead to a hefty increase in file size, up to 1.7 megabytes in the case of Roboto family.

For this particular app, we only need two styles: a lighter one (Roboto-Thin.ttf) and a heavier one (Roboto-Medium.ttf), which we assign to fn_regular and fn_bold respectively:

from kivy.core.text import LabelBase

LabelBase.register(name='Roboto',
                   fn_regular='Roboto-Thin.ttf',
                   fn_bold='Roboto-Medium.ttf')

This code should be placed right after the __name__ == '__main__' line in main.py, as it needs to run before the interface is created from the Kivy language definition. By the time the app class is instantiated, it might already be too late to perform basic initialization like this. This is why we have to do it in advance.

Now that we have a custom font in place, all that's left is to assign it to our Label widget. This can be done with the help of the following code:

# In clock.kv
Label:
    text: '00:00:00'
    font_name: 'Roboto'
    font_size: 60

Formatting text

The most popular and universally used markup language out there is undoubtedly HTML. Kivy, on the other hand, implements a variant of BBCode, a markup language once used to format posts on many message boards. Visible distinction from HTML is that BBCode uses square brackets as tag delimiters.

The following tags are available in Kivy:

BBCode tag

Effect on text

[b]...[/b]

Bold

[i]...[/i]

Italic

[font=Lobster]...[/font]

Change font

[color=#FF0000]...[/color]

Set color with CSS-like syntax

[sub]...[/sub]

Subscript (text below the line)

[sup]...[/sup]

Superscript (text above the line)

[ref=name]...[/ref]

Clickable zone, <a href="…"> in HTML

[anchor=name]

Named location, <a name="…"> in HTML

Tip

This is by no means an exhaustive reference because Kivy is under active development and has probably undergone a number of releases since this text was written, adding new features and refining the existing functionality. Please refer to the Kivy documentation found on the official website (http://kivy.org) for an up-to-date reference manual.

Let's return to our project. To achieve the desired formatting (hours in bold and the rest of the text in fn_regular thin font), we can use the following code:

Label:
    text: '[b]00[/b]:00:00'
    markup: True

Kivy's BBCode flavor works only if we also set the markup property of a widget to True, as shown in the preceding code. Otherwise, you will literally see the string [b]…[/b] displayed on the screen, and that's clearly not desired.

Note that if we wanted to make the whole text bold, there is no need to enclose everything in [b]…[/b] tags; we could just set the bold property of the widget to True. The same applies to italic, color, font name, and size—pretty much everything can be configured globally to affect the whole widget without touching markup.

Changing the background color

In this section, we will adjust the window background color. Window background (the "clear color" of OpenGL renderer) is a property of a global Window object. In order to change it, we add this code right after the __name__ == '__main__' line in main.py:

from kivy.core.window import Window
from kivy.utils import get_color_from_hex

Window.clearcolor = get_color_from_hex('#101216')

The get_color_from_hex function is not strictly required, but it's nice as it allows us to use CSS-style (#RRGGBB) colors instead of (R, G, B) tuples throughout our code. And using CSS colors is preferable for at least the following two reasons:

  • Less cognitive overhead when reading: The #FF0080 value is immediately recognized as a color when you're familiar with this notation, while (255, 0, 128) is just a bunch of numbers that may be used differently depending on the context. The floating-point variant of #FF0080, (1.0, 0.0, 0.50196) is even worse.
  • Simple and unambiguous searching: A tuple can be arbitrarily formatted, while a CSS-like color notation is uniform, albeit case-insensitive. Performing a case-insensitive search in most text editors is very simple, as opposed to locating all instances of a given tuple inside a lengthy Python listing. The latter task can prove challenging and involve regular expressions, among other things, because the formatting of tuples doesn't have to be consistent.

Tip

More information about the #RRGGBB color format can be found on Mozilla Developer Network at https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Getting_started/Color.

We will talk more about design-related features of Kivy later on. Meanwhile, let's make our application actually show the time.