About widgets¶
In the Colorpicker program, we only used the widgets QLabel
,
QSlider
, and QSpinBox
.
However, Qt includes many more of them.
As with programming in general, this course material is not attempting to
instruct you in using all of them.
Instead, we will practice the use of widgets in the following exercises.
One of the new widgets you will encounter is QPushButton
.
If you are going to continue your studies of software engineering after you have completed this course, it is good for you to familiarize yourself with Qt documentation on widgets, which includes the most recent information about all the widgets in the library.
Parent-child mechanism¶
First of all, the parent-child mechanism has nothing to do with inheritance but more to do with memory management. The children of a widget are those widgets that lie inside the widget. For example, a dialog may contain buttons and sliders.
The parent-child mechanism is implemented in the class QObject
,
i.e. it concerns also other objects besides widgets.
When we create an object with a parent, the parent adds the object
to the list of its children.
When the parent is destructed, it goes through this list and destructs
each child.
This makes the children to destruct their children and so on.
The parent-child mechanism simplifies memory management, since it
reduces the risk of memory leaks.
The only objects, for which we must call the delete
command,
are those we created with new
and that have no parent.
If we destruct a child before its parent, Qt automatically removes
that child from the children list of the parent.
Especially for widgets, the parent has an additional meaning: child widgets are shown within the parent’s area. When we delete the parent widget, not only does the child vanish from the memory, it also vanishes from the screen.
Naming objects in Qt¶
The user interface of the program can be edited during the execution by adding widgets as children of the main window. The widgets that are added like this, i.e. during the execution of the program, do not necessarily have variable names. (Widgets can lack variable names in some other situations as well.)
For these situations, Qt has the option of naming widgets by calling
the method setObjectName
.
After this, it is possible to search for widgets by using the various find
methods of the object QObject
.
On this course we mainly use Qt Designer, and it
automatically names objects such as pushButton
, pushButton_2
, etc.
However, it allows you to change object names with the
selection changeObjectName
in the list of elements on the right.
Widget names are important in the automated tests. They may require that you have used certain names. Because of this, some of the assignments define how you should name the widgets.
User interface with Qt Designer vs. as C++ code¶
On this course, the widgets were added into the user interface via Qt Designer. This way has some downsides which we will first study with the help of the dice game example. You are familiar with the dice game from the previous programming course. In the game, the user can cast several dice.
Since the user interface has the Roll button that handle many
QLabel
objects in the same way (at the same time), and several
Keep buttons working in the same way,
nobody wants to edit program code
that has stored QLabel
objects and QPushButton
objects into separate
variables (die1
, die2
, die3
, etc.).
The best way to implement a set of objects that operate with the same
idea is to call the constructor of the widget class in a loop structure,
and to store the created objects into a suitable data structure
(e.g. vector
or map
).
While implementing the Tkinter user interfaces, that way of acting was
natural because the interface had to be assembled by writing Python
program code in any case.
After getting to know Qt Designer, you might think it is boring to write the
user interface in C++.
However, using Qt Designer, we will end up with a set of objects named
button1
, button2
, button3
, etc.
When using Qt Designer, it is useful to know that the widgets that are
positioned using the layout can be accessed via the method of Qt’s layout
objects, itemAt
.
You can then handle the objects in the loop structure because you know their
index in the layout.
Tip
If iterating a certain part of the layout is difficult, you can also use any suitable STL container to store the pointers that point to the widgets you want to handle as a group (i.e. in a similar way).
The other downside is that the user interfaces created with Qt Designer do not scale right when you scale the window larger or smaller. You can see that in the figures below.
If you implement the user interface in code, you will not need the file
with the suffix ui
at all.
All the widgets are created in program code, just like any other objects.
We will practice this way of implementing graphical user interfaces
on the next programming course.