Tutorial: graphical user interface (GUI) for RPi in Qt

.

Background

The purpose of this tutorial is to give the reader a quick introduction into development of graphical user interfaces (GUI for short) in the Qt framework developed and build directly on the Raspberry Pi.

This tutorial is based on the 0x2F design, which is a simple digital input/output module that plugs into the hub of the Pi Top RPi-based laptop.

0x2F module mounted in a Pi Top

 

The 0x2F circuit board features five LEDs, five pushbuttons, and a piezo electric buzzer. All three elements are ideal for simple electronics prototyping and software development.

Our goal is to link the physical circuit board to a stand-alone program developed in Qt with C++ and link the user-interactions between the hardware and software through a GUI.

At the end of the tutorial we will have developed a neat, albeit simple, GUI that allows us to take complete control over the physical circuit board from the Raspberry Pi using either a pointing device (mouse) or even better – a touch screen.

GUI in action. Buzzer sounding at 587 Hz, buttons B and D have been pressed

 

First step is to install Qt on the Raspberry Pi operating system. The installation including the integrated development environment is quite large, so at least a 16 GB SD card should be considered, preferably have a 32 GB ready.

From a terminal enter the following three commands sequentially:

 

We will be relying on the wiringPi library for interfacing with the RPi GPIOs. Hence, we need to make sure that wiringPi is installed and the library is available for Qt.

From the command line, enter the following:

 

Library files are copied during the installation to the folders /usr/local/include and /usr/local/lib respectively.

 

Upon succesful installation of Qt and wiringPi, launch Qt, create a new project, and link the wiringPi library.

Click New project.

Qt opening screen

 

Select Qt Widgets Application and click Choose.

Selection of project type

 

Give your project a suitable name. Create the project files in the appropriate (sub) folder.

Project naming dialog box

 

Select the Desktop kit and click Next.

Kit selection dialog

 

Keep the default file names. Click next.

Project file naming dialogĀ 

 

Click Finish.

Project management dialog

 

Now, Qt creates the project and the various files in the selected folder. In the file explorer window, left hand side, the current five project files are listed. The first file, GUI_tutorial.PRO, is the project file, where wiringPi needs to be linked.

 

Click on the GUI_tutorial.PRO file.

Fresh project .PRO file

 

The entries starting with TARGET and TEMPLATE are generated by Qt.

GUI_tutorial.PRO file editing

 

The following LIBS entry has to be added to the .PRO file for linking wiringPi (remember, everything is case sensitive):

 

The -lwiringPi part is needed for GPIO access and -lpthread allows generating tones to be played by the buzzer.

 

If we were to add support for a Hitachi HD44780U compatible LCD display (e.g. needed in the 0x2A design), we would also link wiringPiDev as shown here and include the lcd.h header in subsequent project files:

 

Now, open the mainwindow.h file.

mainwindow.h

 

We will be using different modules for our program (wiringPi, softTone, and QTimer) and they have to be included in the mainwindow.h file.

 

Modify the top of the file to obtain the following:

 

Next, open the main.cpp file.

main.cpp

 

Again, the modules and header files have to be included. Modify the top of the file to get the following:

 

Finally, open the mainwindow.cpp file, which also happens to be, where most of the magic will take place later.

mainwindow.cpp

 

Modify the top of the file, so you have the following:

 

That concludes the initial setup of the various project files.

 

Next, open the mainwindow.h file.

mainwindow.h

 

Go the part of the file starting with ‘private:’ and enter the following:

These variables tell, whether a pushbutton is pressed or not.

 

Expand the section with states for the LEDs:

 

Add a variable for the buzzer frequency as well:

 

ThenĀ  a timer (the suffix 10 reminds us that it is a 10 ms timer):

 

The last additions to this section of the file are functions for executing various actions:

 

Above the block of code, you just edited, add the following for private slots:

 

That concludes editing of the mainwindow.h file for now.

 

Open mainwindow.cpp.

mainwindow.cpp

 

Below the includes, add the following:

 

This seems like a lot of comments, but is a great help for keeping track of various parts in the code and also to ensure that the code can be read, understood, and maintained by somebody else.

This specific block will deal with declaration of constants, as indicated in the function description. A brief note explains the functionality in more detail than given in the function name itself. Required libraries, modules etc. can be stated too. Finally, a status, whether the code works or it is buggy, is provided. Make sure that you develop and debug each small block of code and change the status to ‘done’. That way, you have a good feeling with the workflow and any pending tasks.

 

First, we declare which GPIO pins are used for controlling LEDs. Add the following to the code block:

 

For convenience we collect these five variables in an array. Add the following:

 

Secondly, we declare, which GPIO pins are connected to pushbuttons. Add the following:

 

Again, collect the variables in an array:

 

Lastly, we define, which GPIO is used for controlling the buzzer:

 

Now, the entire code block should look like this:

 

The next section in the mainwindow.cpp file is the constructor. Add the following comments:

 

In this section, we will initialise the various modules, setup wiringPi for GPIO access, setup the timer, and customise the GUI.

 

Qt already generated the following code:

 

Immediately after the line with ui->setupUP(this) – and before the righthand curly braces – we will add our initialisation code. First, we add a status message, which will appear by default in the lower left hand corner of the GUI. Add the following:

 

Next, we initialise the 10 ms timer:

 

Then, wiringPi is set up:

 

Directions for GPIO pins controlling LEDs are set using pinMode in a for loop (that is why we created the array):

 

Similarly, we configure GPIOs connected to pushbuttons as being inputs:

 

Then, the buzzer is set up:

 

State variables are initialised:

 

Buzzer frequency variable is initialised:

 

Lastly, we configure the GUI window:

 

That concludes our modification of the constructor. Next we move on to the destructor.

 

Qt already created the destructor:

 

Add the following comments above it:

 

Next, we define a way to end the application programmatically. Add the following:

 

A function for reading state of pushbuttons is achieved with the following:

 

Then, we define a function for turning all five LEDs off at once. Add the following:

 

Similar, we define a way to illuminate all five LEDs in one go. Add:

 

The buzzer is controlled with the following code (note the status – we will finalise the block later):

 

Silencing the buzzer is achieved with:

 

Sounding the buzzer at 1 kHz is done by:

 

That concludes editing of the text based project files for now. Next, we switch to designing the graphical user interface.

Click on the mainwindow.ui file.

mainwindow.ui. Initial looks

 

The procedure is simply dragging so called widgets from the menus on the left hand side and dropping them onto the design area. Lots of parameters for widgets can be adjusted in the menu on the right hand side and by right-clicking and selecting various menus.

 

First, we set the design area to 800 x 400:

GUI size adjusted to 800×400

 

Next, we drag and drop a pushbutton widget onto the design area:

Pushbutton widget added

 

Resize the pushbutton to 100×100:

Pushbutton resized

 

Rename the button (the button text) by double clicking on it:

Pushbutton renamed to ‘red’

 

Rename the pushbutton object name (important step!) to pushbutton_LED_RED:

Pushbutton object name changed

 

Repeat the procedure and add four more buttons:

Five pushbuttons created

 

Drop a Line Edit widget onto the design area:

Line Edit widget placed

 

Resize to 100×100 and rename the object to textPushbutton_A:

Line Edit widget resized and renamed

 

Add another four Line Edit widgets and do resizing and renaming for these also:

Five Line Edit widgets created and renamed

 

Add a pushbutton for sounding the buzzer and adjust the size to 200×50:

Pushbutton widget for sounding buzzer

 

And a pushbutton for silencing the buzzer:

Pushbutton for silencing buzzer

 

Add a horisontal slider widget, adjust its size to 250×50, and rename it to slider_BUZZER:

Slider widget placed and adjusted

 

Go to the properties menu and set maximum to 5000 and tick scales on both sides with an interval of 500:

Slider widget range adjusted

 

Add an LCD Number widget, adjust its size to 150×50, and rename it to lcd_BUZZER_FREQUENCY:

LCD Number widget placed and formatted

 

Set the digit count to 4:

LCD Number widget changed to display four digits

 

Add four more pushbuttons for illuminating all LEDs, blanking all LEDs, clearing pushbutton text boxes, and quitting the application:

Four more pushbutton widgets added

 

Right click the pushbutton with the label ‘Red’ and select the menu point Go to slot. Then, click OK:

Right-clicking the ‘red’ pushbutton

 

This brings us back to the mainwindow.cpp file, where Qt has created a function for the action you just requested:

 

Modify it to get the following:

 

Do the same for the other four pushbuttons related to LEDs.

 

The pushbutton action, that causes all LEDs to light up, should contain the following:

 

Similarly, for turning off all five LEDs:

 

Clearing pushbutton text boxes can be done with:

 

For that to work, one more function needs to be added to mainwindow.cpp:

 

Sounding the buzzer:

 

Silencing the buzzer:

 

Selecting an arbitrary frequency using the slider:

 

One more function needs to be added to the mainwindow.cpp file:

 

Finally, modify the buzzer function:

 

That concludes the various aspects of creating a GUI for the 0x2F design. It is left as an exercise to compile and debug the few typos that likely have found their way to the code. A functional set of source files can be downloaded from the mentioned design website. The text editor Notepad++ is excellent for reviewing the files on a Windows machine.

.

Comments are closed.