Buttons

Buttons are interactive user interface elements, which usually react upon mouse events such as clicks or similar events.

Button

You already learned about the Button widget in an earlier section, so let us look at some interesting details of it now.

The Button widget is a interactive widget, which reacts upon mouse input such as clicks. Basically it is a container (which will be explained detailled later on), which holds a Label widget to display its text.

To create a Button, you usually will type

button = Button (text)
        

The usage of mnemonics for the Button is easy to achieve by simply supplying a mnemonic text as described in the section called “Labels”. You can set the text directly through the text attribute or set_text() method.

button.text = "#Mnemonic"
button.set_text ("#Mnemonic")
        
It is not needed to explicitly set the widget attribute of the Button its Label as this already has been done on creation of the Button.

As one of only few widgets the Button supports different border styles to adjust its look and feel without the need to override its drawing methods.

button.border = BORDER_NONE
button.set_border (BORDER_NONE)
        

The Button widget has some default signals, it listens to. Those are

  • SIG_MOUSEDOWN - Invoked, when a mouse button is pressed down on the Button.

  • SIG_MOUSEUP - Invoked, when a mouse button is released on the Button.

  • SIG_MOUSEMOVE - Invoked, when the mouse moves over the Button area.

  • SIG_CLICKED - Invoked, when the left mouse button is pressed and released over the Button.

Below you will find an example to illustrate most of the abilities of the Button widget class. You do not need to care about other widgets like the Frame class for now as those are explained later on.

You can find the following example as a python script under examples/button.py.

# Button examples.
import os
from ocempgui.widgets import *
from ocempgui.widgets.Constants import *

def _create_vframe (text):
    frame = VFrame (Label (text))
    frame.spacing = 5
    frame.align = ALIGN_LEFT
    return frame

def create_button_view ():
    states = ("STATE_NORMAL", "STATE_ENTERED", "STATE_ACTIVE",
              "STATE_INSENSITIVE")

    table = Table (2, 3)
    table.spacing = 5

    # Frame with the states.
    frm_states = _create_vframe ("States")
    for i in xrange (len (states)):
        btn = Button (states[i])
        if STATE_TYPES[i] == STATE_INSENSITIVE:
            btn.sensitive = False
        else:
            btn.state = STATE_TYPES[i]
        frm_states.add_child (btn)
    table.add_child (0, 0, frm_states)
    table.set_align (0, 0, ALIGN_TOP)

    # Frame with different padding.
    frm_padding = _create_vframe ("Padding")
    for i in xrange (5):
        btn = Button ("Padding: %dpx" % (i * 2))
        btn.padding = i * 2
        frm_padding.add_child (btn)
    table.add_child (0, 1, frm_padding)
    table.set_align (0, 1, ALIGN_TOP)

    # Mnemonics.
    frm_mnemonic = _create_vframe ("Mnemonics")
    btn = Button ("#Simple Mnemonic")
    btn2 = Button ("#Activate using <ALT><Underlined Key>")
    frm_mnemonic.add_child (btn, btn2)
    table.add_child (0, 2, frm_mnemonic)
    table.set_align (0, 2, ALIGN_TOP)

    # Borders.
    frm_borders = _create_vframe ("Borders")
    btn_raised = Button ("Raised border")
    btn_sunken = Button ("Sunken border")
    btn_sunken.border = BORDER_SUNKEN
    btn_flat = Button ("Flat border")
    btn_flat.border = BORDER_FLAT
    btn_none = Button ("No border")
    btn_none.border = BORDER_NONE
    btn_etchedin = Button ("Etched in")
    btn_etchedin.border = BORDER_ETCHED_IN
    btn_etchedout = Button ("Etched out")
    btn_etchedout.border = BORDER_ETCHED_OUT
    frm_borders.add_child (btn_raised, btn_sunken, btn_flat, btn_none,
                           btn_etchedin, btn_etchedout)
    table.add_child (1, 0, frm_borders)
    table.set_align (1, 0, ALIGN_TOP)

    # Multiline labeled buttons
    frm_multiline = _create_vframe ("Multiline labels")
    strings = ("Single lined Button", "Two lines on" + os.linesep + "a Button",
               "Two lines with a" + os.linesep + "#mnemonic")
    for i in xrange (len (strings)):
        button = Button (strings[i])
        button.child.multiline = True
        frm_multiline.add_child (button)
    table.add_child (1, 1, frm_multiline)
    table.set_align (1, 1, ALIGN_TOP)
    
    return table
    
if __name__ == "__main__":
    # Initialize the drawing window.
    re = Renderer ()
    re.create_screen (550, 470)
    re.title = "Button examples"
    re.color = (234, 228, 223)
    re.add_widget (create_button_view ())
    # Start the main rendering loop.
    re.start ()

Example 24. Button example

ImageButton

The ImageButton is basically a subclass of the Button, but enhances it by the ability to load and display image data. It supports any image data format, that can be handled by the underlying pygame library. Due to its inheritance, everything said about the Button widget applies to the ImageButton as well.

The creation of an ImageButton is slightly different to the Button. Instead of passing the text to display, you can pass either the name of a file to load (including the full path to it) or a pygame.Surface object to display.

button = ImageButton ("path/to/an/image.png")
button = ImageButton (pygame_surface)
        
Of course it is possible to supply text through the text attribute, too, which then will be displayed right besides the image.
button.text = "Additional text"
        

Below you will find an example to illustrate most of the abilities of the ImageButton widget class. You do not need to care about other widgets like the Frame class for now as those are explained later on.

You can find the following example as a python script under examples/imagebutton.py.

# ImageButton examples.
import pygame, os
from ocempgui.draw import Image
from ocempgui.widgets import *
from ocempgui.widgets.Constants import *

def _create_vframe (text):
    frame = VFrame (Label (text))
    frame.spacing = 5
    frame.align = ALIGN_LEFT
    return frame

def create_button_view ():
    states = ("STATE_NORMAL", "STATE_ENTERED", "STATE_ACTIVE",
              "STATE_INSENSITIVE")

    image = Image.load_image ("./image.png")
    table = Table (2, 2)
    table.spacing = 5

    # Frame with the states.
    frm_states = _create_vframe ("States")
    for i in xrange (len (states)):
        btn = ImageButton (image)
        if STATE_TYPES[i] == STATE_INSENSITIVE:
            btn.sensitive = False
        else:
            btn.state = STATE_TYPES[i]
        btn.text = states[i]
        frm_states.add_child (btn)
    table.add_child (0, 0, frm_states)
    table.set_align (0, 0, ALIGN_TOP)

    # Frame with different padding.
    frm_padding = _create_vframe ("Padding")
    for i in xrange (4):
        btn = ImageButton (image)
        btn.padding = i * 2
        frm_padding.add_child (btn)
    table.add_child (0, 1, frm_padding)
    table.set_align (0, 0, ALIGN_TOP)

    # Mnemonics.
    frm_mnemonic = _create_vframe ("Mnemonics")
    btn = ImageButton (image)
    btn.text = "#Simple Mnemonic"
    btn2 = ImageButton (image)
    btn2.text = "#Activate using <ALT><Underlined Key>"
    frm_mnemonic.add_child (btn, btn2)
    table.add_child (1, 0, frm_mnemonic)
    table.set_align (1, 0, ALIGN_TOP)

    # Multiline labeled ImageButton
    frm_multiline = _create_vframe ("Multiline label")
    button = ImageButton (image)
    button.text = "Multiple lines" + os.linesep + "with a #mnemonic"
    button.child.multiline = True
    frm_multiline.add_child (button)
    table.add_child (1, 1, frm_multiline)
    table.set_align (1, 1, ALIGN_TOP)

    return table

if __name__ == "__main__":
    # Initialize the drawing window.
    re = Renderer ()
    re.create_screen (570, 400)
    re.title = "ImageButton examples"
    re.color = (234, 228, 223)
    re.add_widget (create_button_view ())
    # Start the main rendering loop.
    re.start ()

Example 25. ImageButton example

ToggleButton

Inherited from the Button the ToggleButton widget does not differ from it except that it is always in one state, either active or inactive, which are alternated by a click. By default it is displayed in a depressed state on a click and pops up after clicking it again.

To create a ToggleButton, you can do the same as with the Button class.

button = ToggleButton (text)
        

You can retrieve the current state as boolean value of the ToggleButton through its active attribute and set its state programmatically via this attribute or the set_active() method.

if button.active:
    print "The ToggleButton is currently active!"
button.set_active (False)
        
This also applies to the CheckButton and RadioButton classes in the next sections.

To track changes of this state, the ToggleButton supplies a SIG_TOGGLED signal, which will be raised, if the state is changed via a mouse input or the accelerator action of a Label.

def state_changed (togglebutton):
    state = "active"
    if not togglebutton.active:
       state = "inactive"
    out = "The state of the ToggleButton has been set to %s" % state

button = ToggleButton ("A ToggleButton")
button.connect_signal (SIG_TOGGLED, state_changed, button)
        
The signal will not be raised, if the state is set programmatically.

Below you will find an example to illustrate most of the abilities of the ToggleButton widget class. You do not need to care about other widgets like the Frame class for now as those are explained later on.

You can find the following example as a python script under examples/togglebutton.py.

# ToggleButton examples.
import os
from ocempgui.widgets import *
from ocempgui.widgets.Constants import *

def _create_vframe (text):
    frame = VFrame (Label (text))
    frame.spacing = 5
    frame.align = ALIGN_LEFT
    return frame

def create_button_view ():
    states = ("STATE_NORMAL", "STATE_ENTERED", "STATE_ACTIVE",
              "STATE_INSENSITIVE")

    table = Table (2, 3)
    table.spacing = 5

    # Frame with the states.
    frm_states = _create_vframe ("States")
    for i in xrange (len (states)):
        btn = ToggleButton (states[i])
        if STATE_TYPES[i] == STATE_INSENSITIVE:
            btn.sensitive = False
        else:
            btn.state = STATE_TYPES[i]
        frm_states.add_child (btn)
    table.add_child (0, 0, frm_states)
    table.set_align (0, 0, ALIGN_TOP)

    # Frame with different padding.
    frm_padding = _create_vframe ("Padding")
    for i in xrange (5):
        btn = ToggleButton ("Padding: %dpx" % (i * 2))
        btn.padding = i * 2
        frm_padding.add_child (btn)
    table.add_child (0, 1, frm_padding)
    table.set_align (0, 0, ALIGN_TOP)

    # Mnemonics.
    frm_mnemonic = _create_vframe ("Mnemonics")
    btn = ToggleButton ("#Simple Mnemonic")
    btn2 = ToggleButton ("#Activate using <ALT><Underlined Key>")
    frm_mnemonic.add_child (btn, btn2)
    table.add_child (0, 2, frm_mnemonic)
    table.set_align (0, 2, ALIGN_TOP)


    # Multiline labeled buttons
    frm_multiline = _create_vframe ("Multiline labels")
    strings = ("Single lined ToggleButton",
               "Two lines on" + os.linesep + "a ToggleButton",
               "Two lines with a" + os.linesep + "#mnemonic")
    for i in xrange (len (strings)):
        button = ToggleButton (strings[i])
        button.child.multiline = True
        frm_multiline.add_child (button)
    table.add_child (1, 0, frm_multiline)
    table.set_align (1, 0, ALIGN_TOP)

    return table

if __name__ == "__main__":
    # Initialize the drawing window.
    re = Renderer ()
    re.create_screen (530, 400)
    re.title = "ToggleButton examples"
    re.color = (234, 228, 223)
    re.add_widget (create_button_view ())
    # Start the main rendering loop.
    re.start ()

Example 26. ToggleButton example

CheckButton

The CheckButton, which inherits from the ToggleButton, does not bring in any new features. Instead it just uses a different look to display its set state. The state of the CheckButton is indicated by a small (usually 10x10 px) square, which is either checked or unchecked.

To create a CheckButton widget, you usually will do the same as with the ToggleButton.

button = CheckButton (text)
        

Below you will find an example to illustrate most of the abilities of the CheckButton widget class. You do not need to care about other widgets like the Frame class for now as those are explained later on.

You can find the following example as a python script under examples/checkbutton.py.

# CheckButton examples.
import os
from ocempgui.widgets import *
from ocempgui.widgets.Constants import *

def _create_vframe (text):
    frame = VFrame (Label (text))
    frame.spacing = 5
    frame.align = ALIGN_LEFT
    return frame

def create_button_view ():
    states = ("STATE_NORMAL", "STATE_ENTERED", "STATE_ACTIVE",
              "STATE_INSENSITIVE")

    table = Table (2, 3)
    table.spacing = 5

    # Frame with the states.
    frm_states = _create_vframe ("States")
    for i in xrange (len (states)):
        btn = CheckButton (states[i])
        if STATE_TYPES[i] == STATE_INSENSITIVE:
            btn.sensitive = False
        else:
            btn.state = STATE_TYPES[i]
        frm_states.add_child (btn)
    table.add_child (0, 0, frm_states)
    table.set_align (0, 0, ALIGN_TOP)

    # Frame with different padding.
    frm_padding = _create_vframe ("Padding")
    frm_padding.spacing = 5
    frm_padding.align = ALIGN_LEFT
    for i in xrange (5):
        btn = CheckButton ("Padding: %dpx" % (i * 2))
        btn.padding = i * 2
        frm_padding.add_child (btn)
    table.add_child (0, 1, frm_padding)
    table.set_align (0, 0, ALIGN_TOP)

    # Mnemonics.
    frm_mnemonic = _create_vframe ("Mnemonics")
    btn = CheckButton ("#Simple Mnemonic")
    btn2 = CheckButton ("#Activate using <ALT><Underlined Key>")
    frm_mnemonic.add_child (btn, btn2)
    table.add_child (0, 2, frm_mnemonic)
    table.set_align (0, 2, ALIGN_TOP)

    # Multiline labeled buttons
    frm_multiline = _create_vframe ("Multiline labels")
    strings = ("Single lined CheckButton",
               "Two lines on" + os.linesep + "a CheckButton",
               "Two lines with a" + os.linesep + "#mnemonic")
    for i in xrange (len (strings)):
        button = CheckButton (strings[i])
        button.child.multiline = True
        frm_multiline.add_child (button)
    table.add_child (1, 0, frm_multiline)
    table.set_align (1, 0, ALIGN_TOP)

    return table

if __name__ == "__main__":
    # Initialize the drawing window.
    re = Renderer ()
    re.create_screen (550, 350)
    re.title = "CheckButton examples"
    re.color = (234, 228, 223)
    re.add_widget (create_button_view ())
    # Start the main rendering loop.
    re.start ()

Example 27. CheckButton example

RadioButton

RadioButton widgets are similar to the CheckButton widgets, except that they can grouped, so that only one button of a group can be activated at a time. This is especially helpful, if you need to have the user to choose between a small amount of options.

The creation of a RadioButton is done using

button = RadioButton (text, group)
        
The additional group argument can contain another RadioButton object, with which the newly created one should be grouped together.

Alternatively to the group argument of the constructor, a RadioButton can be assigned to a group after its creation with the group attribute or set_group() method.

button.group = other_radio_button
button.set_goup (other_radio_button)
        
It is also possible to go the other way around and to add or remove RadioButton widgets from a group with the add_button() or remove_button() methods of the group.

Given those possibilities a group of four choices can be created like the following example.

group = RadioButton ("Choice 1")
button1 = RadioButton ("Choice 2", group)

button2 = RadioButton ("Choice 3")
button2.group = group

button3 = RadioButton ("Choice 4")
group.add_button (button3)
        

In contrast to its parent classes, activating a RadioButton causes the other buttons in its group to loose their active state.

Below you will find an example to illustrate most of the abilities of the RadioButton widget class. You do not need to care about other widgets like the Frame class for now as those are explained later on.

You can find the following example as a python script under examples/radiobutton.py.

# RadioButton examples.
import os
from ocempgui.widgets import *
from ocempgui.widgets.Constants import *

def _create_vframe (text):
    frame = VFrame (Label (text))
    frame.spacing = 5
    frame.align = ALIGN_LEFT
    return frame

def create_button_view ():
    states = ("STATE_NORMAL", "STATE_ENTERED", "STATE_ACTIVE",
              "STATE_INSENSITIVE")

    table = Table (2, 3)
    table.spacing = 5

    # Frame with the states.
    frm_states = _create_vframe ("States")
    group = None
    for i in xrange (len (states)):
        btn = RadioButton (states[i], group)
        if i == 0:
            group = btn
        if STATE_TYPES[i] == STATE_INSENSITIVE:
            btn.sensitive = False
        else:
            btn.state = STATE_TYPES[i]
        frm_states.add_child (btn)
    table.add_child (0, 0, frm_states)
    table.set_align (0, 0, ALIGN_TOP)

    # Frame with different padding.
    frm_padding = _create_vframe ("Padding")
    group = None
    for i in xrange (5):
        btn = RadioButton ("Padding: %dpx" % (i * 2), group)
        if i == 0:
            group = btn
        btn.padding = i * 2
        frm_padding.add_child (btn)
    table.add_child (0, 1, frm_padding)
    table.set_align (0, 0, ALIGN_TOP)

    # Mnemonics.
    frm_mnemonic = _create_vframe ("Mnemonics")
    btn = RadioButton ("#Simple Mnemonic")
    btn2 = RadioButton ("#Activate using <ALT><Underlined Key>", btn)
    frm_mnemonic.add_child (btn, btn2)
    table.add_child (0, 2, frm_mnemonic)
    table.set_align (0, 2, ALIGN_TOP)

    # Multiline labeled buttons
    frm_multiline = _create_vframe ("Multiline labels")
    strings = ("Single lined RadioButton",
               "Two lines on" + os.linesep + "a RadioButton",
               "Two lines with a" + os.linesep + "#mnemonic")
    group = None
    for i in xrange (len (strings)):
        btn = RadioButton (strings[i], group)
        if i == 0:
            group = btn
        btn.child.multiline = True
        frm_multiline.add_child (btn)
    table.add_child (1, 0, frm_multiline)
    table.set_align (1, 0, ALIGN_TOP)

    return table

if __name__ == "__main__":
    # Initialize the drawing window.
    re = Renderer ()
    re.create_screen (550, 330)
    re.title = "RadioButton examples"
    re.color = (234, 228, 223)
    re.add_widget (create_button_view ())
    # Start the main rendering loop.
    re.start ()

Example 28. RadioButton example