Catto / Topic Map · Computer Science II Level 2
Computer Science II · 120 h · Topic 5 of 8

Graphical user interfaces

A graphical interface inverts control: the program no longer commands, it waits. That change of mindset —from the sequential program to the event loop— is what you have to understand first.

Events Widgets Event loop Callbacks Design

01The program stops being in charge

A console program is in charge: it asks for a value, calculates, prints, ends. A graphical interface reverses that relationship. The program starts, draws the window and waits; the one who decides what happens is the user.

Sequential programEvent-driven program
The code controls the orderThe user controls the order
scanf blocks until there is dataNothing blocks: you are notified when something happens
Starts and endsLives in a loop until the window is closed
A single line of executionMany handlers, each one short
The event loop

Underneath every graphical interface there is the same loop, whatever it is called:

while the window is open:
    event = get_from_queue() # waits if there is none
    handler = find_handler_for(event)
    handler(event)
    redraw_what_changed()

The operating system deposits every click, every key press and every mouse movement into that queue. The program takes them out one at a time and calls the corresponding handler.

Lab · the event loop, in slow motion

Use the controls below: each action queues an event. Process them one at a time and see which handler runs.

02Widgets and containers

An interface is built from widgets —the controls— placed inside containers that decide how they are arranged. The container tree is what lets the window adapt when it is resized, instead of having everything in fixed coordinates.

WidgetWhat it is forEvent it generates
ButtonTriggering an actionclick
Text fieldTyping a valuechange, key, focus
Checkbox and radio buttonChoosing between alternativesstate change
SliderA continuous valuechange, many times per second
List and tableShowing and choosing recordsselection
CanvasFree drawingredraw, mouse

There are two approaches to arranging them: absolute positions —quick to do, but they break as soon as the size or the font changes— and layout managers by rows, columns or grid, which is always the better choice.

03Separating the interface from the logic

The rule that prevents the most problems: a button’s handler does not do the work, it only calls whatever does. If the calculation, the measurement or the access to the device is written inside the handler, it cannot be tested without opening the window, nor reused from a script.

def on_press_measure(): # handler: three lines
    v = instrument.measure_voltage() # the logic, separate
    label.config(text=f"{v:.3f} V")
    chart.add(v)

That is the core of the patterns studied under their own names —model-view-controller and its variants—: the model holds the data and the rules, the view displays them and the controller translates events into calls to the model.

Never block the loop

If a handler takes two seconds, the window is frozen for two seconds: it does not redraw, does not respond and the system marks it as “not responding”. Anything that takes time —reading a port, downloading, heavy calculation— goes in another thread, and when it finishes it notifies the interface. The rule is strict: only the interface thread may touch the widgets; the others send it the result through a queue or through the mechanism the library provides.

04An instrumentation interface

In electronics, the interface almost always accompanies a piece of equipment: a measurement bench, a process control, a recorder. What is expected of it:

  • Visible status. Connected or not, on which port, since when.
  • Continuous reading without blocking. One thread reads the instrument; the interface refreshes every 100 or 200 ms, not at 60 frames per second.
  • Units and significant figures. Show 3.7 V, not 3.700000001.
  • Logging and export. Saving the series as CSV is the first thing anyone using it will ask for.
  • Errors in plain sight. If the equipment was disconnected, say so; do not leave the last value frozen.
  • Confirmation of anything dangerous. A power output is not turned on with a careless click.
ToolkitLanguageWhere it fits
TkinterPythonComes with Python; ideal for getting started and for internal tools
Qt (PyQt / Qt in C++)Python or C++Large, cross-platform applications with graphics
Dear ImGuiC++Debugging panels and lab tools
Local web interfaceAny + browserThe device serves a page; it is used from any machine

05In the lab

Exercise 1 · Logging the events

Build a window with a button, a field and a slider, and make each handler print to the console which event arrived. Move the slider and count how many events a single drag generates.

Exercise 2 · Freezing the window on purpose

Put a sleep(3) inside a button’s handler and check that the interface goes dead. Then move that work to a thread and verify that the window stays alive.

Exercise 3 · A panel for the microcontroller

Using the protocol from the previous page, build an interface that turns an output on and off, sets a PWM with a slider and shows the sensor reading on a scrolling chart.

06Common mistakes

  • Doing heavy work in the handler and freezing the window.
  • Touching widgets from another thread. It is the cause of the hardest crashes to reproduce.
  • Mixing the logic with the interface and being left with no way to test anything.
  • Positioning everything in absolute coordinates and having it break when the size changes.
  • Redrawing the entire chart at 60 frames per second when the data changes ten times per second.
  • Not reporting the error and leaving the last value on screen as if it were current.

07Self-assessment

What is the event loop?

The cycle that takes events from the queue, calls the corresponding handler and redraws. Every graphical interface has one.

Why does a window freeze?

Because a handler is taking a long time and the loop cannot keep processing events or redrawing.

Can a worker thread update a label directly?

No: only the interface thread may touch the widgets. The worker thread sends it the result through a queue or through the mechanism the library provides.

How many events does dragging a slider generate?

Many, one for each change of value. That is why a slider’s handler has to be cheap, or the real work has to be spaced out.

What advantage does a layout manager have over fixed coordinates?

The window adapts when the size, resolution or font changes, without the controls overlapping.

What does the model-view-controller pattern separate?

The data and rules (model), what is displayed (view) and the translation of events into actions (controller). It allows testing the logic without opening the window.

08Further reading

  • Mark Summerfield. Rapid GUI Programming with Python and Qt. Prentice Hall, 2007. Events, threads and interface design with a real-application mindset.
  • Official Python documentation. tkinter — Interface to Tcl/Tk. Python Software Foundation. The library that comes already installed: enough for most lab tools.
  • Jakob Nielsen. Usability Engineering. Morgan Kaufmann, 1993. The classic heuristics: visibility of status, error prevention, user control.
Development of the topic “Graphical user interfaces” of Computer Science II (Level 2), based on the curriculum of the UTN Electronic Engineering program, 2023 curriculum — Ordinance No. 1849 of the UTN Higher Council. Back to the Topic Map · catto.ar