Welcome to Tingbot GUI’s documentation!

Contents:

Getting Started

Let’s build a simple application to get started - a colour [1] picker. Any colour can be described with three numbers - red, green and blue [2] , so we’re going to have three sliders, and a button to display the chosen colour.

Setup

To use this software in a tingapp we have to tell it that the library is required. You will need to create requirements.txt if it does not already exist. Add the following to this file to ensure that the tingbot_gui library is loaded:

tingbot-gui>=0.9

Alternatively the library can be installed by pip install tingbot-gui

Next lets create main.py and import all the relevant libraries:

from tingbot import screen, run
import tingbot_gui as gui

#all the rest of the code goes here

def loop():
    pass

screen.fill("black")
gui.show_all()
run(loop)

This imports the tingbot_gui library and renames it gui to simplify the typing. We create an (empty) run loop, and set the whole system going. The second to last line ensures that all of the widgets added are shown. All the rest of the code below should be inserted just below the line that states #all the rest of the code goes here

Add some sliders

Lets add some sliders to allow the user to select the individual colour elements. We’ll put these on the right hand side of the screen

red = gui.Slider((190,20),(25,150),align="top",max_val=255)
green = gui.Slider((240,20),(25,150),align="top",max_val=255)
blue = gui.Slider((290,20),(25,150),align="top",max_val=255)

This adds three sliders, one for each colour. We set their position with first pair of numbers, and the size within the second pair. The align="top" means that the red slider is positioned with the middle of its top border at (180,20).

Add a button

Now we need to make something happen. Let’s add a button, and also create a callback to display the chosen color when it is pressed

def display():
    color = (int(red.value),int(green.value),int(blue.value))
    screen.rectangle((20,20),(100,100),color,align="topleft")

button = gui.Button((240,200),(80,30),align="top",label="Display",callback=display)

This creates a function display which creates a color with values determined by the value of each of the sliders. We use int to ensure that the values are integers. screen.rectangle draws the selected colour on the screen. The last line creates a button labelled “Display”, and tells it to call the display function when it is pressed. Note that there is no pair of brackets in the reference to display. This means that the function itself is passed to the Button. If we put callback=display() then the result of the function would be passed (which would be None). At this point you will be able to get your colour picker up and running, but it’s not very pretty...

Add some labels

It’s not obvious which slider is red, green or blue, so lets add some labels next

gui.StaticText((190,0),(50,20),align="top",label="Red")
gui.StaticText((240,0),(50,20),align="top",label="Green")
gui.StaticText((290,0),(50,20),align="top",label="Blue")

Again we have used the “top” alignment - this allows us to make sure that all the labels are correctly centered. StaticText will automatically centre its label unless you tell it otherwise. Note that we have not assigned these labels to variables. Because we are not going to do anything more with these labels, we can just declare them.

Add some clever labels with lambda

Lets finally add some numbers to each slider to reflect it’s current value.

red_label = gui.StaticText((190,180),(50,20),label="0")
green_label = gui.StaticText((240,180),(50,20),label="0")
blue_label = gui.StaticText((290,180),(50,20),label="0")

def update_label(label,value):
    label.label = str(int(value))

red.callback = lambda x: update_label(red_label,x)
green.callback = lambda x: update_label(green_label,x)
blue.callback = lambda x: update_label(blue_label,x)

First of all we create some more labels - red_label, green_label and blue_label, and we next take a function update_label that takes a label and a value and sets that label to display that value as an integer.

Finally we use a special keyword lambda. This creates a temporary function, as if we had written

def temp_func(x):
    return update_label(red_label,x)

red.callback = temp_func

See the section on Callbacks for more on how to use callbacks and lambda.

Add an alert

Lets add a little pop-up notice with the Web RGB code when we display our colour. Lets change the display function.

def display():
    color = (int(red.value),int(green.value),int(blue.value))
    screen.rectangle((20,20),(100,100),color,align="topleft")
    gui.message_box(message="RGB code is #%02X%02X%02X" % color)

This will bring up a window on top of the screen to tell you what the Web RGB code is. This uses the convenience function message_box() to display the RGB code. The code will stop here until the user presses on “Ok”.

Footnotes

[1]I’m British, so I use the english spelling of colour. However, historically the majority of software was written in the USA, so in software, the standard is to spell it color.
[2]Actually there are several ways of specifying a colour, many of which are better than simple red green and blue. However, red green and blue is simplest, so we’ll stick with that for this example. See the Wikipedia entry on color spaces for more detail than you can possibly want.

Widgets

There are several different elements that can be used in an interface, known as widgets

class Widget(xy, size, align = "center", parent = None)

This is the base class for all other widgets, but should not be directly used. All other widgets will have the methods listed below. You can make your own widgets by sub-classing this one. You will need to override the draw method, and possibly the on_touch method. All of the screen drawing methods (fill, rectangle, image and line) are also available within this class. See the tingbot-python reference for these methods.

Parameters:
  • xy – position that the widget will be drawn
  • size – size of the widget
  • align – one of topleft, left, bottomleft, top, center, bottom, topright, right, bottomright
  • parent (Container) – container for this widget. If None, widget will be placed directly on the main screen
  • style (Style) – style for this widget. If None, the widget will have the default style
Attributes:
  • visible – True if the widget is to be displayed. Widget will be hidden if false
  • surface – A pygame surface that corresponds to the widgets area - use this in the draw method
on_touch(self, xy, action)

Override this method for any widgets that respond to touch events

Parameters:
  • xy – position of the touch
  • action – one of “up”, “move”, “down”, “drag”, “drag_up”. The first touch is recorded as “down”. If the touch moves, this is passed as a “move” and when the touch finishes an “up” action is passed. If the widget is within a ScrollArea then as the touch moves the ScrollArea may start moving it’s viewable area - this is passed as a “drag” (and finishes with a “drag_up”). Widgets may wish to ignore “drag” and “drag_up” events as the user likely wanted to interact with the ScrollArea rather than the specific widget.
update(self, upwards=True, downwards=False)

Call this method to redraw the widget. The widget will only be drawn if visible. It is usually wise to call this function after you have altered a widget.

Parameters:
  • upwards – set to True to ask any parents (and their parents) to redraw themselves
  • downwards – set to True to make any children redraw themselves
draw(self)

Called when the widget needs to draw itself. Override this method for all derived widgets

text(self, string, xy=None, size=None, color='grey', align='center', font=None, font_size=32, antialias=None)

Draw some text on to the widget. If the text will not fit on the widget or in size if specified, then try using a smaller font to see if that will fit, minimum 3/4 specified font size. If the text will still not fit, then truncate the text and add an ellipsis (...).

Parameters:
  • string – text to displayed
  • xy – location to display the text within the widget. If none will be aligned within the widget according to align
  • size – size for the text to fit within. If None will be fitted within whole widget
  • color – color for the text. Can be either a text string e.g. “blue” or a RGB e.g (0,0,255)
  • align – one of topleft, left, bottomleft, top, center, bottom, topright, right, bottomright
  • font – font to use (or the default font if None)
  • font_size (int) – size of font to use
  • antialias (bool) – whether to antialias the text
Returns:

a list of the x offsets after each letter

class Button(xy, size, align="center", parent=None, style=None, label="OK", callback=None, long_click_callback)

Base: Widget

A simple button control

Parameters:
  • xy – position that the button will be drawn
  • size – size of the button
  • align – one of topleft, left, bottomleft, top, center, bottom, topright, right, bottomright
  • parent (Container) – container for this button. If None, button will be placed directly on the main screen
  • style (Style) – style for this button. If None, the button will have the default style
  • label – Text to be displayed on the button. If starts with image: then the rest of the string specifies an image file to be displayed on the button.
  • callback (callable) – function to call when the button is pressed. It should not take any arguments
  • long_click_callback (callable) – function to call when the button has been pressed for more than 1.5 seconds. It should not take any arguments
Attributes:
  • label – Text to be displayed on the button. If starts with image: then the rest of the string specifies an image file to be displayed on the button. Two image files can be specified by separating them with a |. The second image will be used when the button is pressed
  • callback – Function to be called when button is clicked. No arguments passed.
  • long_click_callback – Function to be called when button is pressed for more than 1.5 seconds. No arguments passed. See Callbacks for more information
Style Attributes:
 
  • bg_color – background color
  • button_color – color of this button when not pressed
  • button_pressed_color – color to use when button pressed
  • button_rounding – rounding in pixels of button corners. use 0 for square corners
  • button_text_color – color to use for text
  • button_text_font – font to use (default)
  • button_text_font_size – font size to use
  • button_cancel_on_leave – if True (default), cancel a button press if the touch leaves the button before release
Example:
def cb(text):
    print text

button1 = gui.Button((0,0),(100,25),align="topleft",label="Button 1",
             callback = lambda: cb("Button 1"),
             long_click_callback = lambda: cb("Button 1(long"))
button2 = gui.Button((0,30),(100,25),align="topleft",label="image:player_play.png|player_play_pressed.png",
                     callback = lambda: cb("Button 2(image)"))
_images/button_demo.png
class ToggleButton(xy, size, align="center", parent=None, style=None, label="OK", callback=None)

Base: Widget

A button which can be in an on or off state

Parameters:
  • xy – position that the button will be drawn
  • size – size of the button
  • align – one of topleft, left, bottomleft, top, center, bottom, topright, right, bottomright
  • parent (Container) – container for this button. If None, button will be placed directly on the main screen
  • style (Style) – style for this button. If None, the button will have the default style
  • label – Text to be displayed on the button. If starts with image: then the rest of the string specifies an image file to be displayed on the button.
  • callback (callable) – function to call when the button is pressed. It should accept a single boolean value
Attributes:
  • label – Text to be displayed on the button. If starts with image: then the rest of the string specifies an image file to be displayed on the button.
  • pressed – Current state of the button. True if pressed, False if not
  • callback – Function to be called when button is clicked. A boolean value is passed which is the current state of the button. See Callbacks for more information
Style Attributes:
 
  • bg_color – background color
  • button_color – color of this button when not pressed
  • button_pressed_color – color to use when button pressed
  • button_rounding – rounding in pixels of button corners. use 0 for square corners
  • button_text_color – color to use for text
  • button_text_font – font to use (default)
  • button_text_font_size – font size to use
  • button_cancel_on_leave – if True (default), cancel a button press if the touch leaves the button before release
Example:
def cb(text,value):
    print text,value

button2 = gui.ToggleButton((0,30),(100,25),align="topleft",label="Toggle",
                            callback = lambda x: cb("Toggle Button",x))
class StaticText(xy, size, align="center", parent=None, style=None, label="", text_align="center")

Base: Widget

A static text control

Parameters:
  • xy – position that the text widget will be drawn
  • size – size of the area for text
  • align – one of topleft, left, bottomleft, top, center, bottom, topright, right, bottomright
  • parent (Container) – container for this text. If None, text will be placed directly on the main screen
  • style (Style) – style for this text. If None, the text will have the default style
  • label – Text to display
  • text_align – alignment of text within the widget
Attributes:
  • label – text
  • text_align – alignment of the text
Style Attributes:
 
  • bg_color – background color
  • statictext_color – color to use for text
  • statictext_font – font to use (default)
  • statictext_font_size – font size to use
Example:
Create a static text widget with a dark red background
text = gui.StaticText((0,220),(320,20),align="topleft",
                      label="Static Text"
                      style=gui.Style(bg_color=(30,0,0)))
class Slider(xy, size, align = "center", parent = None, style = None, max_val=1.0, min_val=0.0, step = None, callback=None)

Base: Widget

A sliding control to allow selection from a range of values

Parameters:
  • xy – position that the slider will be drawn
  • size – size of the slider
  • align – one of topleft, left, bottomleft, top, center, bottom, topright, right, bottomright
  • parent (Container) – container for this slider. If None, slider will be placed directly on the main screen
  • style (Style) – style for this slider. If None, the slider will have the default style
  • max_val (float) – maximum value for the slider
  • min_val (float) – minimum value for the slider
  • step – amount to jump by when clicked outside the slider handle. Defaults to one tenth of max_val-min_val
  • callback (callable) – function called when the slider is moved. Passed a float which is the sliders new value
  • release_callback (callable) – function called when the slider is released. Passed a float which is the sliders latest value
Attributes:
  • value – Current value of the slider
  • callback – Function to be called when the slider is moved. A single float is passed.
  • release_callback – Function to be called when the slider has finished moving. A single float is passed. See Callbacks for more information
Style Attributes:
 
  • bg_color – background color
  • slider_line_color – color of the line
  • slider_handle_color – color of the handle
Example:
Create a horizontal slider with a range of 40-100
def cb(text,value):
    print text,value

gui.Slider((0,0),(200,30),align="topleft",
           max_val=100, min_val=40, step=10,
           callback = lambda x: cb("Slider H",x))

Base: Widget

A widget that displays its current value, and shows a pop-up menu when clicked, allowing the useer to select a new value from a preset list

Parameters:
  • xy – position that the checkbox will be drawn
  • size – size of the checkbox
  • align – one of topleft, left, bottomleft, top, center, bottom, topright, right, bottomright
  • parent (Container) – container for this checkbox. If None, checkbox will be placed directly on the main screen
  • style (Style) – style for this checkbox. If None, the checkbox will have the default style
  • values – a list of (label,data), one for each menu item. Alternatively [label1,label2,label3] can be used
  • callback (callable) – callback is a function to be called when the selected item is changed. It is passed two arguments, label and data.
Attributes:
  • values – a list of (label,data), one for each menu item
  • selected – currently selected menu item as a tuple (label,data)
  • callback – callback is a function to be called when the selected item is changed. It is passed two arguments, label and data. The label is the new label for the control and data is any associated data (if no data was passed in the constructor, then data will be None). See Callbacks for more information
Style Attributes:
 
  • bg_color – background color
  • button_color – color of this button when not pressed
  • button_pressed_color – color to use when button pressed
  • button_rounding – rounding in pixels of button corners. use 0 for square corners
  • button_text_color – color to use for text
  • button_text_font – font to use (default)
  • button_text_font_size – font size to use
  • button_cancel_on_leave – if True (default), cancel a button press if the touch leaves the button before release
  • popup_bg_color – color for the background of the popup
  • popupmenu_button_size – default size for the menu items
  • popupmenu_button_class – set this to define a custom button class (for example if you want to add icons etc to it). This class must have the same __init__ parameters as Button.
Example:
Create a dropdown menu with three options, one with associated data, the other two without
def cb(label, data):
    print "Dropdown selected: ", label, data

dropdown1 = gui.DropDown((0,60),(100,25),align="topleft",
                         parent = button_panel.scrolled_area,
                         values = ("one",("two","data for item two"),"three"),
                         callback = cb)
class CheckBox(xy, size, align="center", parent=None, style=None, label="OK", callback=None)

Base: Widget

A checkbox control

Parameters:
  • xy – position that the checkbox will be drawn
  • size – size of the checkbox
  • align – one of topleft, left, bottomleft, top, center, bottom, topright, right, bottomright
  • parent (Container) – container for this checkbox. If None, checkbox will be placed directly on the main screen
  • style (Style) – style for this checkbox. If None, the checkbox will have the default style
  • label – Text to display
  • callback (callable) – function to call when the button is pressed. Is passed True if checkbox ticked, False otherwise
Attributes:
  • label – Text to be displayed.
  • value – Current status of the checkbox - True for checked, False for unchecked
  • callback – Function to be called when the checkbox is clicked. Is passed True if checkbox ticked, False otherwise See Callbacks for more information
Style Attributes:
 
  • bg_color – background color
  • checkbox_color – color of the checkbox
  • checkbox_text_color – color to use for text
  • checkbox_text_font – font to use (default)
  • checkbox_text_font_size – font size to use
Example:
Create a checkbox control
def cb(label, data):
    print label, data

gui.CheckBox((0,0),(100,25), align="topleft",
             label="Checkbox",
             callback=lambda x:cb("Checkbox",x))

Radio Buttons

Radio buttons are similar to checkboxes, but only one in a group can be selected at any one time. As they need to be part of a group, a RadioButton cannot exist by itself - it needs to be part of a RadioGroup.

Example: create a set of radiobuttons
group = gui.RadioGroup()
radio1 = gui.RadioButton((100,80),(200,20),label="Radio 1",value=1,group=group)
radio2 = gui.RadioButton((100,110),(200,20),label="Radio 2",value=2,group=group)
radio3 = gui.RadioButton((100,140),(200,20),label="Radio 3",value=3,group=group)
class RadioGroup(callback = None)

Base: object

A group of RadioButtons

Parameters:

callback (callable) – function to call when one of the radio buttons is pressed. Will be passed two arguments - first is the buttons label, second is it’s value See Callbacks for more information

Attributes:
  • selected – Currently selected RadioButton
class RadioButton(xy, size, align="center", parent=None, style=None, label="", value=None, group=None, callback=None)

Base: Widget

A radio button control

Parameters:
  • xy – position that the radio button will be drawn
  • size – size of the radio button
  • align – one of topleft, left, bottomleft, top, center, bottom, topright, right, bottomright
  • parent (Container) – container for this radio button. If None, radio button will be placed directly on the main screen
  • style (Style) – style for this radio button. If None, the radio button will have the default style
  • label – Text to display
  • value – Value for this RadioButton, set to label if not specified
  • group (RadioGroup) – RadioGroup that this Button will be part of.
  • callback (callable) – function to call when the button is pressed. It should not take any arguments
Attributes:
  • label – text to displayed
  • value – data associated with this radio button
  • pressed – whether this radio button is pressed or not
  • callback – function to call when the radio button is pressed. It should not take any arguments See Callbacks for more information
Style Attributes:
 
  • bg_color – background color
  • radiobutton_color – color of the RadioButton
  • radiobutton_text_color – color to use for text
  • radiobutton_text_font – font to use (default)
  • radiobutton_text_font_size – font size to use

Input

There are two widgets that can be used to enter text, and one dialog

class Keyboard(label, text="", style=None, callback=None)

Base: Dialog

This dialog box allows you to enter text using an on-screen keyboard. It has lower case, upper case, number and symbols screen. There is a button to add emojis, but it is not currently functional

Parameters:
  • label – Text to display at the top of the dialog e.g. “Username”
  • text – Text to put in the box for editing e.g. “JohnSmith4001”
  • style (Style) – style for this keyboard. If None, the keyboard will have the default style
  • callback (callable) – Function to call when the keyboard is exited. It will be passed a single variable which is the completed string (or None if cancel is pressed)
Attributes:
  • callback – Function to call when the keyboard is exited. It will be passed a single variable which is the completed string (or None if cancel is pressed). See Callbacks for more information
Style Attributes:
 
  • bg_color – background color
  • textentry_bg_color – color of text entry box
  • textentry_text_color – color to use for text
  • textentry_text_font – font to use (default)
  • textentry_text_font_size – font size to use
  • button_color – color of the buttons when not pressed
  • button_inverting – if True, the buttons will use bg_color for text and button_text_color for background when pressed. If False, will use button_pressed_color as background color when pressed
  • button_pressed_color – color to use when buttons pressed
  • button_rounding – rounding in pixels of button corners when button_inverting is False. use 0 for square corners
  • button_text_color – color to use for text
  • button_text_font – font to use (default)
  • statictext_color – color to use for text at top of screen (i.e. Cancel, Title, Ok)
  • statictext_font – font to use (default)
  • statictext_font_size – font size to use
Example:
def cb(text):
    print text

Keyboard("Text", "Happy World!", callback=cb)
_images/Keyboard.png
class TextEntry(xy, size, align="center", parent=None, style=None, label="", text="", callback=None)

Base: Button

A Text entry widget - shows as a box with text inside it. Clicking on the box will bring up a keyboard to enter new text.

Parameters:
  • xy – position that the TextEntry will be drawn
  • size – size of the TextEntry
  • align – one of topleft, left, bottomleft, top, center, bottom, topright, right, bottomright
  • parent (Container) – container for this TextEntry. If None, TextEntry will be placed directly on the main screen
  • style (Style) – style for this TextEntry. If None, the TextEntry will have the default style
  • label – title for the Keyboard when it is shown
  • string – text to display in the TextEntry
  • callback (callable) – Function to call when the string is changed. It will be passed a single variable which is the new string.
Attributes:
  • label – title for the Keyboard when it is shown
  • string – current text of the TextEntry
  • callback – Function to call when the string is changed. It will be passed a single variable which is the new string. See Callbacks for more information
Style Attributes:
 
  • bg_color – background color
  • textentry_bg_color – color of TextEntry box
  • textentry_text_color – color to use for text
  • textentry_text_font – font to use (default)
  • textentry_text_font_size – font size to use
class PasswordEntry(xy, size, align="center", parent=None, style=None, label="", text="", callback=None)

Base: TextEntry

A Password entry widget - shows as a box with a series of dots (•) inside it. Clicking on the box will bring up a keyboard to enter new text (but the current text will not be displayed). Ideal for where you don’t want a passerby to see any passwords.

Parameters:
  • xy – position that the TextEntry will be drawn
  • size – size of the TextEntry
  • align – one of topleft, left, bottomleft, top, center, bottom, topright, right, bottomright
  • parent (Container) – container for this TextEntry. If None, TextEntry will be placed directly on the main screen
  • style (Style) – style for this TextEntry. If None, the TextEntry will have the default style
  • label – title for the Keyboard when it is shown
  • string – text to display in the TextEntry
  • callback (callable) – Function to call when the string is changed. It will be passed a single variable which is the new string.
Attributes:
  • label – title for the Keyboard when it is shown
  • string – current text of the TextEntry
  • callback – Function to call when the string is changed. It will be passed a single variable which is the new string. See Callbacks for more information
Style Attributes:
 
  • bg_color – background color
  • textentry_bg_color – color of TextEntry box
  • textentry_text_color – color to use for text
  • textentry_text_font – font to use (default)
  • textentry_text_font_size – font size to use

Containers

Containers can be used to group widgets together. ScrollAreas can be used to access more widgets than can fit on the screen otherwise.

class Container

Base: Widget

A base class for ScrollAreas and Panels

add_child(self, widget)
Parameters:widget (Widget) – The widget to be added to this container

Adds a widget to this container. This should rarely be called as the widget will call this itself on initiation

remove_child(self, widget)
Parameters:widget (Widget) – The widget to be added to this container

Remove a widget from this container

remove_all(self)

Removes all widgets from the container

class Panel(xy, size, align="center", parent=None, style=None)

Base: Container

Panel class, allows you to collect together various widgets and turn on or off as needed

Parameters:
  • xy – position that the widget will be drawn
  • size – size of the widget
  • align – one of topleft, left, bottomleft, top, center, bottom, topright, right, bottomright
  • parent (Container) – container for this widget. If None, widget will be placed directly on the main screen
  • style (Style) – style for this widget. If None, the widget will have the default style
class ScrollArea(xy, size, align="center", parent=None, style = None, canvas_size=None)

Base: Container

ScrollArea gives a viewing area into another, usually larger area. This allows the user to access more widgets than will fit on the display. Scrollbars will be added to the bottom or right edges as needed. The ScrollArea can be moved by dragging within its area. A fast drag will initiate a “flick” where the ScrollArea carries on scrolling after the drag finishes. It will gradually slow and stop, unless it runs out of room.

Parameters:
  • xy – position that the widget will be drawn
  • size – size of the widget
  • align – one of topleft, left, bottomleft, top, center, bottom, topright, right, bottomright
  • parent (Container) – container for this widget. If None, widget will be placed directly on the main screen
  • style (Style) – style for this widget. If None, the widget will have the default style
  • canvas_size – size of the scrollable area (required)
Attributes:
  • scrolled_area – Use this as the parent for any widgets you wish to place within this container
Style Attributes:
 
  • scrollbar_width – width of the scrollbars
  • slider_line_color – color of the line
  • scrollarea_flick_decay – speed that a flick decreases by in pixels per second per second (default 600)
  • scrollarea_min_flick_speed – speed below which a flick stops in pixels per second (default 60)
  • scrollarea_flick_threshold – speed required to generate a flick in pixels per second (default 100)
  • slider_handle_color – color of the handle
resize_canvas(self, canvas_size)
Parameters:canvas_size – size of the scrollable area

Resize the scrollable area. Will raise an error if the given size is smaller than required to display all the widgets

Example:
Create a scrolled area with a size of (500,500)
    scroller = gui.ScrollArea((100,0),(135,220),align="topleft",canvas_size=(500,500))
class RootWidget

Base: Container

There is only ever one RootWidget and it is generated automatically. All widgets that do not explicitly have a parent set are children of this widget.

get_root_widget()

Returns the RootWidget

show_all()

Tells the RootWidget to display all it’s children. It’s generally useful to call this function immediately before calling the main run loop - this ensures that all the children you have added are drawn on the screen when the program starts.

class NoteBook(pairs)

Base: object

A NoteBook allows you to control a set of Panels with a set of ToggleButtons. Set all of the panels to cover the same area, and pressing each button will make the associated panel visible, and hide the others. ScrollAreas can also be used.

Parameters:pairs – a list of the form [(button1,panel1), (button2,panel2) ...]. panel1,panel2 etc should all occupy the same screen real estate, whereas button1,button2 should be in distinct locations.
Example: create three panels and buttons and use them to create a NoteBook
but1 = gui.ToggleButton((30,30),(60,60),label="1")
but2 = gui.ToggleButton((30,100),(60,60),label="2")
but3 = gui.ToggleButton((30,170),(60,60),label="3")
panel1 = gui.Panel((0,70),(320,170))
panel2 = gui.Panel((0,70),(320,170))
panel3 = gui.Panel((0,70),(320,170))

nb = NoteBook([(but1,panel1), (but2,panel2), (but3,panel3)])

Dialog windows

Dialog windows are modal - this means that only the specified window is active while it is open This is particularly useful for alert boxes and also pop-up menus

class Dialog(xy=None, size=None, align="center", style=None, buttons=None, message="", cancellable=True, callback=None, transition="popup")

Base: Container

Dialog is a base class you can use to create your own dialogs. Call close to make the dialog disappear. Place widgets with self.panel as the parent, not self

Parameters:
  • xy – position that the dialog will be drawn
  • size – size of the dialog
  • align – one of topleft, left, bottomleft, top, center, bottom, topright, right, bottomright
  • style (Style) – style for this dialog. If None, the dialog will have the default style
  • cancellable (bool) – If true, then the dialog can be closed by clicking outside its area. Any callback specified will be passed None as it’s argument
  • callback (callable) – A callback that will be called when the dialog is closed, one argument is passed, which is whatever the close method is called with.
  • transition
    • “popup” – the dialog appears on screen as specified by xy, size and align.
    • “slide_left” – the dialog slides in to the left, width as per size, xy and align ignored
    • “slide_right” – the dialog slides in to the right, width as per size, xy and align ignored
    • “slide_left” – the dialog slides in downwards, height as per size, xy and align ignored
    • “slide_left” – the dialog slides in upwards, height as per size, xy and align ignored
Attributes:
  • cancellable – If true, then the dialog can be closed by clicking outside its area. Any callback specified will be passed None as it’s argument
  • callback – A callback that will be called when the dialog is closed, one argument is passed, which is whatever the close method is called with. See Callbacks for more
  • panel – A panel to place widgets on - this allows the dialog to implement the sliding operation
Style Attributes:
 
  • scrollbar_width – width of the scrollbars
  • slider_line_color – color of the line
  • slider_handle_color – color of the handle
close(self, ret_value=None)
Parameters:ret_value – value to be returned to the callback function

Close this modal window and return ret_value to the callback function

run(self)

Runs the dialog in blocking mode - i.e. execution of other code will stop until the dialog has been closed. Scheduled events via once and every will continue to run.

Returns:whatever self.close was called with
class MessageBox(xy=None, size=None, align="center", style=None, buttons=None, message="", cancellable=True, callback=None)

Base: Dialog

A MessageBox allows you to alert the user to simple events, and also ask simple Yes/No type questions

Parameters:
  • xy – position that the dialog will be drawn (in the centre if None)
  • size – size of the dialog, (280x200 if None)
  • align – one of topleft, left, bottomleft, top, center, bottom, topright, right, bottomright
  • style (Style) – style for this MessageBox. If None, the MessageBox will have the default style
  • buttons – A list of labels for buttons to be shown. Three can be displayed with the default window size and button size. Defaults to [“OK”] if None
  • message (string) – Text to display in the MessageBox
  • cancellable (bool) – If true, then the MessageBox can be closed by clicking outside its area. Any callback specified will be passed None as it’s argument
  • callback (callable) – A callback that will be called when the MessageBox is closed, one argument is passed, which is the label of the button that was pressed (or None if cancelled)
Attributes:
  • cancellable – If true, then the MessageBox can be closed by clicking outside its area. Any callback specified will be passed None as it’s argument
  • callback – A callback that will be called when the MessageBox is closed, one argument is passed, which is the label of the button that was pressed (or None if cancelled) See Callbacks for more
Style Attribute:
 
  • bg_color – background color
  • button_color – color of buttons when not pressed
  • button_pressed_color – color to use when button pressed
  • button_rounding – rounding in pixels of button corners. use 0 for square corners
  • button_text_color – color to use for button text
  • button_text_font – font to use (default font if None)
  • button_text_font_size – font size to use
  • messagebox_button_size – size to use for buttons
  • statictext_color – color to use for message text
  • statictext_font – font to use (default font if None)
  • statictext_font_size – font size to use
Example:
Find out if the user likes cheese
    def cb(name,value=None):
        print name, value

    gui.MessageBox(message="Do you like cheese?",
                   buttons=["Yes","No","Maybe"],
                   cancellable=False,
                   callback = lambda x:cb("Cheese?",x))
message_box(xy=None, size=None, align="center", style=None, buttons=None, message="", cancellable=True)

Utility function. Call this to create a message_box, wait until a button is pressed, and return the value of that button (or None if cancellable is true and the user clicks outside the box)

Parameters:
  • xy – position that the dialog will be drawn (in the centre if None)
  • size – size of the dialog, (280x200 if None)
  • align – one of topleft, left, bottomleft, top, center, bottom, topright, right, bottomright
  • style (Style) – style for this MessageBox. If None, the MessageBox will have the default style
  • buttons – A list of labels for buttons to be shown. Three can be displayed with the default window size and button size. Defaults to [“OK”] if None
  • message (string) – Text to display in the MessageBox
  • cancellable (bool) – If true, then the MessageBox can be closed by clicking outside its area. Any callback specified will be passed None as it’s argument
Example:
Find out if the user likes cheese
    cheese_preference = gui.message_box(message="Do you like cheese?",
                                        buttons=["Yes","No","Maybe"])
class PopupMenu(xy, style=None, cancellable=True, menu_items=None, button_size=None)

Base: Dialog

A PopupMenu (also known as a context menu) allows you to present the user with a menu

Parameters:
  • xy – position for the topleft of the menu. However, the menu may be adjusted so that it fits on the screen. If the menu is so long that it cannot fit on the screen, a scrollbar will be provided
  • style (Style) – style for this PopupMenu. If None, the PopupMenu will have the default style
  • cancellable (bool) – If true, then the PopupMenu can be closed by clicking outside its area.
  • menu_items – is a list of the form [(label,callback)...], one for each entry in the menu. callback takes no arguments and will be called if that menu item selected.
  • button_size – a size parameter for each button in the popupmenu. If none, button_size will be taken from the style.
Attributes:

None

Style Attributes:
 
  • bg_color – background color
  • button_pressed_color – color to use when menu item pressed
  • button_text_color – color to use for text
  • button_text_font – font to use (default)
  • button_text_font_size – font size to use
  • popup_bg_color – color for the background of the popup
  • popupmenu_button_size – default size for the menu items
  • popupmenu_button_class – set this to define a custom button class (for example if you want to add icons etc to it). This class must have the same __init__ parameters as Button.
Example:
Bring up a Popup prompting to Open or Save
    def open_fn():
        print "open"

    def save_fn():
        print "save"

    gui.PopupMenu((160,100), menu_items = [("Open",open_fn), ("Save",save_fn)])

Styles

The appearance of many of the gui components (also known as widgets) are highly configurable. There are three ways to alter the style of the interface

  1. Use the default style. This will affect every single widget, even ones that have already been created.

    Example: alter the background color to blue for every widget
    style = gui.get_default_style()
    style.bg_color = "blue"
    
  2. Use a custom style. This allows you to customize individual widgets or groups of widgets

    Example: create two buttons with a smaller font size
    custom_style = gui.Style(button_text_font_size = 12)
    button1 = gui.Button((50,50),(80,80),label="Small text",style=custom_style)
    button2 = gui.Button((150,50),(80,80),label="Small again",style=custom_style)
    button3 = gui.Button((250,50),(80,80),label="OK")
    

    Custom made styles will all inherit the default settings, so you only need to specify those items that need to be altered

  3. Update a pre-existing style. This allows you to use a pre-existing style and only change those attributes which need to be changed

    Example: update a pre-existing style with a new background_color
    my_new_style = my_old_style.copy(bg_color="teal")
    

Styles can be updated dynamically, even after the widget has been created

class Style(**kwargs)
Parameters:**kwargs – specify style attributes as required
Returns:A new Style with attributes set as per kwargs, all others are as per default settings
copy(self, **kwargs)
Parameters:**kwars – specify style attributes to update as required
Returns:A new Style with attributes set as per kwargs, all others are as per the original style.
get_default_style()
Returns:The default style.

Callbacks

Basic usage

Several classes use callbacks to respond to user events. The simplest of these take no arguments

Example: respond to a button press
def button_callback():
    screen.text("Button pressed")

but = gui.Button((40,40),(80,80),label="Button",callback = button_callback)

Notice that button_callback has no brackets when passed to the Button. Other callbacks will take a value dependent on the state of the widget. For example, the callback for a slider will pass it’s current value as a float

Example: display the value of a slider
def slider_callback(value):
    screen.rectangle((0,0),(320,200),"black","topleft")
    screen.text("%d" % int(value))

slider = gui.Slider((0,200),(320,20),align="topleft",
                    max_val = 200, callback = slider_callback)

Passing extra arguments to callbacks

Sometimes it is useful to pass an extra value to the callback, if you have several widgets, where you want to use the same callback. This can be done using lambda.

Example: display which button was pressed
def button_callback(name):
    screen.rectangle((0,80),(320,240),"black","topleft")
    screen.text("Button %s pressed" % name)

but1 = gui.Button((40,40),(80,80),label="1",callback = lambda : button_callback("1"))
but2 = gui.Button((130,40),(80,80),label="2",callback = lambda : button_callback("2"))
but3 = gui.Button((220,40),(80,80),label="3",callback = lambda : button_callback("3"))

If the callback should be passed a value from the widget, then you need to use the form lambda x: as below.

Example: display which slider has changed
def slider_callback(value,name):
    screen.rectangle((0,0),(320,100),"black","topleft")
    screen.text("Slider %s: %d" % (name,int(value)),(160,50))

sld1 = gui.Slider((120,110),(230,20),max_val=200,
                  callback = lambda x: slider_callback(x,"1"))
sld2 = gui.Slider((120,150),(230,20),max_val=200,
                  callback = lambda x: slider_callback(x,"2"))
sld3 = gui.Slider((120,190),(230,20),max_val=200,
                  callback = lambda x: slider_callback(x,"3"))

For more information about lambda the Mouse vs Python blog is a good summary of the subject.

Full example

Here is a fully worked example including all the widgets available. The top layer is a notebook, with toggle buttons down the left side.

  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
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
#!/usr/bin/env python
from tingbot import screen, run
from tingbot.graphics import _xy_from_align
import tingbot_gui as gui

action_text = gui.StaticText((0,220),(320,20),align="topleft",
                             style=gui.Style(bg_color=(30,0,0)))

def cb(name,value=None):
    text = name + " actioned: " +str(value)
    action_text.label = text
    print text
    action_text.update() 

panel_layouts = {'xy':(85,0),
                 'size':(235,220),
                 'align':"topleft"}
labels = ('Basics','Slider','Text','Buttons','Dialogs','Dynamic')
notebook_style = gui.get_default_style().copy()
notebook_style.bg_color = (25,25,25)
notebook_args = {'size':(80,28),'align':"topleft",'style':notebook_style}
notebook_buttons = [gui.ToggleButton((0,30*i),label=l,**notebook_args) 
                    for i,l in enumerate(labels)]

#basic control panel
basic_panel = gui.Panel(**panel_layouts)
gui.CheckBox((0,0),(100,25), align="topleft",
             label="Checkbox",
             parent = basic_panel, 
             callback=lambda x:cb("Checkbox",x))
radio_group = gui.RadioGroup(callback=cb)
gui.RadioButton((0,30),(100,25),align="topleft",
                label="Radio 1", 
                parent = basic_panel, 
                group = radio_group, 
                callback=lambda :cb("Radio Button 1"))
gui.RadioButton((0,60),(100,25),align="topleft",
                label="Radio 2",  value="R2 value", 
                parent = basic_panel, group = radio_group)
gui.RadioButton((0,90),(100,25),align="topleft",
                label="Radio 3", 
                parent = basic_panel, group = radio_group)

#slider panel
slider_panel = gui.Panel(**panel_layouts)
gui.Slider((0,0),(200,30),align="topleft",
           max_val=100,min_val=40, step=15, 
           parent=slider_panel,
           callback = lambda x: cb("Slider H",x))
gui.Slider((0,40),(30,180),align="topleft",
           parent=slider_panel,
           callback = lambda x: cb("Slider V",x),
           release_callback = lambda x: cb("Slider V Release",x))

#text panel
text_panel = gui.ScrollArea(canvas_size=(500,500),
                            style=gui.Style(bg_color="navy"),
                            **panel_layouts)
positions = ['topleft', 'left', 'bottomleft', 
             'top', 'center', 'bottom', 
             'topright', 'right', 'bottomright']
scrollarea = text_panel.scrolled_area
args = [{'xy':_xy_from_align(x,(500,500)),
         'size':(80,50),
         'align':x,
         'text_align':x,
         'label':x} for x in positions]
texts = [gui.StaticText(parent=scrollarea,**a) for a in args]

#button panel
no_cancel_style = gui.Style(button_cancel_on_leave=False)
button_panel = gui.ScrollArea(canvas_size=panel_layouts['size'],**panel_layouts)
button1 = gui.Button((0,0),(100,25),align="topleft",label="Button 1", 
                     parent = button_panel.scrolled_area, 
                     callback = lambda: cb("Button 1"), 
                     long_click_callback = lambda: cb("Button 1(long)"))
button2 = gui.Button((0,30),(100,25),align="topleft",label="image:player_play.png", 
                     parent = button_panel.scrolled_area, 
                     callback = lambda: cb("Button 2(image)"),
                     style = no_cancel_style) 
button3 = gui.ToggleButton((0,60),(100,25),align="topleft",label="Tog But", 
                            parent = button_panel.scrolled_area, 
                            callback = lambda x: cb("Toggle Button",x))
button4 = gui.ToggleButton((0,90),(100,25),align="topleft",label="Tog But NC", 
                            parent = button_panel.scrolled_area, 
                            callback = lambda x: cb("Toggle Button (no cancel)",x),
                            style=no_cancel_style)
dropdown1 = gui.DropDown((0,120),(100,25),align="topleft",
                         parent = button_panel.scrolled_area, 
                         values = ("DD one",("two","data for item two")),
                         callback = lambda x,y:cb("DropDown1",(x,y)))
dropdown2 = gui.DropDown((0,150),(100,25),align="topleft", 
                         parent = button_panel.scrolled_area, 
                         values = range(100),
                         callback = lambda x,y:cb("DropDown2",(x,y)))
dropdown3 = gui.DropDown((0,190),(100,25),align="topleft", 
                         parent = button_panel.scrolled_area, 
                         values = ("DD 3","two",3,"ridiculously long text here"),
                         callback = lambda x,y:cb("DropDown3",(x,y)))

#dialog panel
class DialogDemo(gui.Dialog):
    def __init__(self,transition):
        if transition in ('slide_left','slide_right'):
            size = (150,240)
        if transition in ('slide_up','slide_down'):
            size = (320,150)
        super(DialogDemo,self).__init__(size=size,transition=transition)
        button = gui.Button(xy=(75,75), size=(50,50), label="ok", callback=self.close, parent=self.panel)
   
dialog_panel = gui.Panel(**panel_layouts)

def alert():
    cb("Alert dialog",gui.message_box(message="Alert triggered"))
    
def question():
    dialog_style = gui.Style(statictext_color="red")
    msg = gui.MessageBox(message="Do you like cheese?\nEven Camembert?",
                         buttons=["Yes","No","Maybe"],
                         cancellable=False,
                         callback = lambda x:cb("Question dialog",x),
                         style=dialog_style)
    msg.run()

def popup(xy = (160,120)):
    gui.popup_menu(xy, menu_items = [("File",lambda: cb("File (Popup)")),
                                     ("Save",lambda: cb("Save (Popup)"))])
                                    
def slide_in():
    for x in ['slide_up','slide_left','slide_down','slide_right']:
        cb("Dialog slide",x)
        DialogDemo(x).run()
    
gui.Button((0,0),(80,25),align="topleft",parent = dialog_panel, 
           label="Alert",callback=alert)
gui.Button((0,30),(80,25),align="topleft",parent = dialog_panel, 
           label="Question",callback=question)
gui.Button((0,60),(80,25),align="topleft",parent = dialog_panel, 
           label="Popup",callback=popup)
gui.Button((0,90),(80,25),align="topleft",parent = dialog_panel, 
           label="Popup2",callback=lambda: popup((310,230)))
gui.Button((0,120),(80,25),align="topleft",parent = dialog_panel, 
           label="Slide-ins",callback=slide_in)
gui.TextEntry((0,150),(160,25),align="topleft",parent = dialog_panel,
           label="Text Entry",callback=lambda x: cb("TextEntry",x))
gui.PasswordEntry((0,180),(160,25),align="topleft",parent = dialog_panel,
           label="Password",callback=lambda x: cb("PasswordEntry",x))

#dynamic list panel
dynamic_panel = gui.Panel(**panel_layouts)
scroller = gui.ScrollArea((100,0),(135,220),align="topleft",
                          parent=dynamic_panel,canvas_size=(135,75))

def make_button(index,pos,text="Dynamic"):
    label = text + ' ' + str(index)
    button = gui.PopupButton((0,pos*25),(135,25),align="topleft",
                             parent = scroller.scrolled_area,
                             label = label,
                             callback = lambda: cb(label))
    return button                         

button_list = [make_button(i,i,"Original") for i in range(3)]
count = 3

def add_item():
    global count
    cb("Add dynamic item",count)
    scroller.resize_canvas((135,(len(button_list)+1)*25))
    button_list.append(make_button(count,len(button_list)))
    count += 1
    scroller.update(downwards=True)

def remove_last_item():
    cb("Remove dynamic item",'last')
    if button_list:
        scroller.scrolled_area.remove_child(button_list.pop())
        scroller.resize_canvas((135,max(len(button_list)*25,10)))
        scroller.update(downwards=True)
    
def remove_all():
    cb("Remove dynamic items",'all')
    scroller.scrolled_area.remove_all()
    scroller.resize_canvas((135,10))
    button_list[:] = []
    scroller.update(downwards=True)

gui.Button((0,0),(90,25),align="topleft",parent=dynamic_panel,
           label="Add item",callback=add_item)
gui.Button((0,30),(90,25),align="topleft",parent=dynamic_panel,
           label="Del last",callback=remove_last_item)
gui.Button((0,60),(90,25),align="topleft",parent=dynamic_panel,
           label="Del all",callback=remove_all)


def nb_cb(button,panel):
    print "Notebook panel changed: " +button.label

notebook_panels = [basic_panel,slider_panel,text_panel,
                   button_panel,dialog_panel,dynamic_panel]
nb = gui.NoteBook(zip(notebook_buttons,notebook_panels),callback = nb_cb)
print "Current notebook tab: " + nb.selected.label

gui.get_root_widget().fill(notebook_style.bg_color)
gui.show_all()
def loop():
    pass

run(loop)

Graphical user interface

This module provides a graphical user interface for the tingbot. It allows you to include some of the commoner elements (also known as widgets) of your phone or computer interface within your application, rather than having to develop them from scratch.

Indices and tables