Want to keep learning?

This content is taken from the Raspberry Pi Foundation & National Centre for Computing Education's online course, Programming with GUIs. Join the course to learn more.

Skip to 0 minutes and 3 seconds Most of the programs you will have written before this course were probably procedural, running instructions from top to bottom, calling functions as they run. GUIs are event driven programs, which means the instructions run when events occur, such as clicking your mouse or pressing a key. So your code must handle these events no matter what order they occur in. Now, let’s take a look at an example. So first, the app window is created. This is a blank canvas which will contain the different widgets your app will use. Next, a function is created. This function will generate a greeting when a button is clicked. But the code won’t run until the event happens. Then the GUI is designed.

Skip to 0 minutes and 45 seconds Each widget is created in code and given a unique name. The PushButtons command is set to call the function when it is clicked. Finally, the GUI is displayed, and the computer waits for the events to be triggered. When the user enters their name and clicks the Done push button, the btn_go_clicked function is run, and the greeting is displayed. When you create an event based app, your program loads, but nothing happens until an event is triggered. It’s a little like a burglar alarm in a house. There are multiple sensors which can activate the alarm, but the siren won’t sound until a window is broken, a door opened, or a sensor triggered.

Skip to 1 minute and 26 seconds In the same way, guizero can recognise more than just clicks on push buttons. Let’s take a look at this example. Can you identify which event highlights the text box when the mouse is hovering over it? Leave your thoughts in the comments. [CLICK]

Understanding event driven programming

The programs you will have written prior to this course were probably procedural programs. Procedural or sequential programs generally run instructions from top to bottom, calling functions as they run.

Event-driven programs such as the one you wrote in the previous step operate somewhat differently to procedural. The main difference is that in an event-driven program, the flow of the program and the order in which instructions are run is determined by events like mouse clicks or keys being pressed on the keyboard.

GUI programs react to user events rather than controlling what the user can do, and code must be able to handle these events no matter the order in which they occur.

For example, in a GUI-based car-ordering system which quotes a price when options are selected, the user might want to start by selecting an engine size from a ButtonGroup, then picking a colour from a ComboBox, or they might choose to start with selecting leather or cloth seats from a ListBox; regardless of how the options are entered, the GUI must be able to update the price.

Lets look in detail at the workflow for the program you have just created:

from guizero import App, TextBox, PushButton, Text, info

app = App()

def btn_go_clicked():
    info("Greetings","Hello, " + txt_name.value + " - I hope you're having a nice day")

lbl_name = Text(app, text="Hello. What's your name?")
txt_name = TextBox(app)
btn_go = PushButton(app, command=btn_go_clicked, text="Done")

app.display()
  1. The App window is created. This is essentially a blank canvas, which will eventually contain the different widgets your app will use.

    app = App()
    

    An animation. The code above is displayed on the left half of the animation. The code "app = App() is highlighted in light blue, and a light blue line from this draws a rectangle on the right hand side of the animation. The blue line fades away to reveal a light grey rectangle with a dashed border.

  2. A function is created that describes what to do when a button is clicked, but no code is run until the event happens.

    def btn_go_clicked():
        info("Greetings","Hello, " + txt_name.value + " - I hope you're having a nice day")
    
  3. The GUI is designed: widgets are created in code, with their own names so that the computer can identify each one uniquely.

    lbl_name = Text(app, text="Hello. What's your name?")
    txt_name = TextBox(app)
    btn_go = PushButton(app, command=btn_go_clicked, text="Done")
    

    An animation. The code above is displayed on the left half of the animation. On the right hand side is a light grey rectangle with a dashed border. The line starting "lbl_name" is highlighted in light blue, and a light blue line moves over to some text reading "Hello. What's your name?", appearing on the right. The light blue highlighting and line disappears. Next the line starting "txt_name" is highlighted, and a light blue line goes from this to draw a faded empty text box on the right, below the previous text. Again the light blue highlighting and line disappears. The line starting "btn_go" is highlighted in light blue, and a light blue line coming from this draws a faded button labelled "Done" underneath the text box. The light blue highlighting and line disappears.

  4. The GUI is displayed. This tells the computer to wait for events to be triggered.

    app.display()
    

    An animation - The code above is displayed on the left half of the animation, and the greyed out version of the GUI is displayed on the right. The text "app.display()" is highlighted in light blue, and a light blue line goes from this to surround the GUI window. The window and the text, textbox and button all become solid, and the light blue hightlight and line disappear.

  5. When the user interacts with the app by entering their name and pressing the ‘Done’ button the btn_go_clicked function will be run and the ‘Info’ box displayed.

An animation - The code above is displayed on the left half of the animation, and the GUI is displayed on the right. The name "Martin" is typed into the text box, and a mouse cursor moves onto the "Done" button and clicks it. The function starting with the "def btn_go_clicked():" line is highlighted, in light blue, and it draws an alert window on top of the GUI, with the title "Greetings" and the text "Hello, Martin - have a nice day".

When you create an event-based app, nothing will happen after your program loads until an event is triggered. This is rather like a burglar alarm in a house. Once the alarm is armed, nothing further will happen until a window is broken, a door opened, or a sensor is triggered, causing the siren to go off.

With our house alarm analogy, there are numerous sensors that can be used to trigger the alarm. In the same way, guizero recognises more than just clicks on PushButtons when coding. Events can be set up for any widget, such as:

  • when_clicked We’ve used this already.
  • when_left_button_pressed This can be used in conjunction with the next event to make buttons appear to change momentarily as they’re clicked.
  • when_left_button_released Normally used along with the previous event.
  • when_mouse_enters Triggered when the mouse cursor enters a widget. Also nice for providing visual cues to your user as they navigate your GUI.
  • when_mouse_leaves Triggered when the mouse leaves a widget.
  • when_mouse_dragged When the mouse is clicked on and then dragged across a widget.

We can set a function to be called by an event attached to a widget like this:

widget_name.when_left_button_pressed = function_name

Note: Unlike calling a function during a program, at this point you should make sure not to put brackets after the function name.

In the following example, the when_mouse_enters and when_mouse_leaves events are used to highlight the TextBox when the mouse is over it by setting its background to light blue.

from guizero import App, TextBox, PushButton, Text, info

app = App()

def btn_go_clicked():
    info("Greetings","Hello, " + txt_name.value + " - I hope you're having a nice day")

def highlight():
    txt_name.bg = "light blue"

def lowlight():
    txt_name.bg = None

lbl_name = Text(app, text="Hello. What's your name?")
txt_name = TextBox(app)

# when the mouse enters the button
txt_name.when_mouse_enters = highlight

# when the mouse leaves the button
txt_name.when_mouse_leaves = lowlight

btn_go = PushButton(app, command=btn_go_clicked, text="Done")

app.display()

An animation - the updated code is on the left hand side, with the GUI on the right hand side. As the mouse cursor moves over the "Done" button the button changes colour to light blue, and as the mouse cursor moves off the button the colour changes back to white.

A full list of events can be seen in the guizero Event pages.

Share this video:

This video is from the free online course:

Programming with GUIs

Raspberry Pi Foundation