CPSC 427a: Object-Oriented Programming
Michael J. Fischer
November 30, 2010
Graphical User Interfaces
User Interfaces Modern computer systems support two primary general-purpose user interaces: Command line: User input is via a command line typed at the keyboard. Output is character-based and goes to a physical or simulated typewriter-like terminal. Graphical User Interface (GUI): User input is via a pointing device (mouse), button clicks, and keyboard. Output is graphical and goes to a window on the screen.
Interfaces for C++
The C++ standard specifies a command line interface: iostream and associated packages. No similar standard exists for GUIs.
De facto GUI standards in the Linux world are GTK+ (used by the Gnome desktop) and Qt (used by the KDE desktop).
GTK+ is based on C; Qt is based on an extension of C++ and requires a special preprocessor.
gtkmm is a C++ wrapper on top of GTK+.
Provides a native interface to C++ code.
Disadvantages: Components not so well integrated.
Documentation spread between gtkmm, gtk+, and other components but improving.
Overall Structure of a GUI
A GUI manages one or more windows.
Each window displays one or more widgets.
These are objects that provide graphical and textual input and output to
A GUI package such as gtkmm maintains a widget tree.
A widget controls a particular kind of user input or output.
Examples: label, text box, drawing area, button, scroll bar, etc.
Concurrency and Events
The central problem in building a GUI is handling concurrency.
Data arrives from multiple concurrent sources – mouse and keyboard,
network, disk, other threads, etc.
We call the arrival of a piece of data an event.
For example, to have a good interactive feel, the GUI should respond to a mouse click event within milliseconds.
An event loop allows a single thread to manage a set of events.
At some level, the hardware or software polls for events.
When an event is detected, it is dispatched to an event handler.
The event handler either processes the event itself, queues a task for
later processing, or spawns a thread to process it.
While the event thread is processing one event, no other events can be
processed, so event handlers should be short.
Problem is to prevent a long-running low-priority event handler from delaying the handling of a high-priority event.
A GUI event structure
A GUI typically translates raw hardware events into semantically-meaningful
For example, a mouse click at particular screen coordinates might turn
into a button-pressed event for some widget in the GUI tree.
Several system layers may be involved in this translation, from the kernel processing of hardware interrupts at the bottom level, up through device drivers, windowing systems such as X, and finally a GUI frameworks such as GTK+.
Interface between user and system code
A major software challenge is how to design the interface between the
GUI and the user code that ultimately deals with the events.
In a command-line interface, the user code is at the top level.
It connects to the lower layers through familiar function calls.
With a GUI, things are turned upside down.
Binding system calls to user functions
How can one write the GUI to call user functions that did not even exist
when the GUI system itself was written?
The basic idea is that of interface.
C++ virtual functions provide an elegant way to bind user code to an interface.
Of course, the actual binding occurs at run time through the use of type tags and the vtable as we have seen before.
Binding through callback registration
The user explicitly registers an event handler with the GUI by calling a special registration function.
This is sometimes called a callback mechanism since the user asks to be called back when an event occurs.
Callback using function pointers: GUI side
Callbacks can be done directly in C. Here’s the GUI code:
Callback using function pointer: User side
Here’s how the user attaches a handler to the GUI:
The above scheme does not generalize well to multiple events with different signatures.
The alternative is for systemRegister() to take a void* for
its second argument and to cast function pointers before call
This is not type safe and can lead to subtle bugs if the wrong type of function is attached to a callback slot.
Signals and slots
Signals and slots is a more abstract way of linking events to handlers and can be implemented in a type safe way.
Several signals can be connected to the same slot, and several slots can be conencted to the same signal.
The gtkmm Framework
Structure of gtkmm gtkmm relies on several libraries and packages:
Compiling a gtkmm program
Many include files and libraries are needed to compile and build a gtkmm program.
A utility pkg-config is used to generate the necessary command line for the compiler.
Linking a gtkmm program
pkg-config also generates the necessary linker flags.
To use package config, use the backquote operator on the g++ command line:
Compiling: g++ -c ‘pkg-config gtkmm-2.4 --cflags‘ ...
Linking: g++ ‘pkg-config gtkmm-2.4 --libs‘ ...
Both: g++ ‘pkg-config gtkmm-2.4 --cflags --libs‘ ...
Using a GUI
The following steps are involved in creating a GUI using gtkmm:
The GUI then displays the window and waits for events.
When an event occurs, the corresponding user code is run.
When the event handler returns, the GUI waits for the next event.
The code example 22-clock is a significant extension of the clock
example in the gtkmm tutorial book.
It illustrates many of the features of gtkmm.