A slightly less toy example

Note

Toga is a work in progress, and may not be consistent across all platforms.

Please check the Tutorial Issues label on Github to see what’s currently broken.

Most applications require a little more than a button on a page. Lets build a slightly more complex example - a Fahrenheit to Celsius converter:

../_images/tutorial-1.png

Here’s the source code:

import toga
from toga.style.pack import *


def build(app):
    c_box = toga.Box()
    f_box = toga.Box()
    box = toga.Box()

    c_input = toga.TextInput(readonly=True)
    f_input = toga.TextInput()

    c_label = toga.Label('Celsius', style=Pack(text_align=LEFT))
    f_label = toga.Label('Fahrenheit', style=Pack(text_align=LEFT))
    join_label = toga.Label('is equivalent to', style=Pack(text_align=RIGHT))

    def calculate(widget):
        try:
            c_input.value = (float(f_input.value) - 32.0) * 5.0 / 9.0
        except:
            c_input.value = '???'

    button = toga.Button('Calculate', on_press=calculate)

    f_box.add(f_input)
    f_box.add(f_label)

    c_box.add(join_label)
    c_box.add(c_input)
    c_box.add(c_label)

    box.add(f_box)
    box.add(c_box)
    box.add(button)

    box.style.update(direction=COLUMN, padding_top=10)
    f_box.style.update(direction=ROW, padding=5)
    c_box.style.update(direction=ROW, padding=5)

    c_input.style.update(flex=1)
    f_input.style.update(flex=1, padding_left=160)
    c_label.style.update(width=100, padding_left=10)
    f_label.style.update(width=100, padding_left=10)
    join_label.style.update(width=150, padding_right=10)

    button.style.update(padding=15, flex=1)

    return box


def main():
    return toga.App('Temperature Converter', 'org.beeware.f_to_c', startup=build)


if __name__ == '__main__':
    main().main_loop()

This example shows off some more features of Toga’s Pack style engine. In this example app, we’ve set up an outer box that stacks vertically; inside that box, we’ve put 2 horizontal boxes and a button.

Since there’s no width styling on the horizontal boxes, they’ll try to fit the widgets they contain into the available space. The TextInput widgets have a style of flex=1, but the Label widgets have a fixed width; as a result, the TextInput widgets will be stretched to fit the available horizontal space. The margin and padding terms then ensure that the widgets will be aligned vertically and horizontally.