qtlabs Documentation Release

Vladimir Poliakov

Aug 21, 2017

Contents

1 Introduction 3 1.1 What is ?...... 3 1.2 Framework...... 3 1.3 Toolkit...... 4

2 Getting started with Qt 5 2.1 Prerequisites...... 5 2.2 Qt installation...... 6 2.3 First project in ...... 12

3 Lab 1. Qt basics 19 3.1 Typical main.cpp file...... 19 3.2 Qt basic modules...... 20 3.3 QObject model philosophy...... 21 3.4 Conclusion and exercise...... 24

i ii qtlabs Documentation, Release

This project aims to give basic knowledges and skills of using Qt framework. There is no special prerequisites, except some essentials in C++.

Contents 1 qtlabs Documentation, Release

2 Contents CHAPTER 1

Introduction

What is Qt?

Qt (“cute”) is the independent technology for cross-platform development of application on desktop, embedded and mobile operating systems. It consists of toolkit, including tools for development, debugging and deployment of application, for cross-platform applications. Qt is usually refereed as a C++ framework and a set of tools for development of graphical interfaces. Indeed, at the current time Qt framework has much more capabilities, including multi-threading, networking, and can be easily integrated with other languages, such as Python, Javascript, SQL , as well as it can be combined with different tools and frameworks, for instance D-Bus and OpenCV. Thus, Qt is a platform of choice for: 1. Desktop applications 2. Mobile applications 3. Embedded systems: • in-vehicle systems • medical equipment • industrial automation devices

Framework

Qt framework includes next modules: 1. QtCore - Core non-graphical classes used by other modules. 2. QtGUI - Base classes for (GUI) components. Includes OpenGL. 3. QtMultimedia - Classes for audio, video, radio and camera functionality. 4. QtNetwork - Classes to make network programming easier and more portable. 5. QtQuick - A declarative framework for building dynamic applications with custom user interfaces.

3 qtlabs Documentation, Release

6. QtSQL - Classes for database integration using SQL. 7. QtTest -Classes for unit testing Qt applications and libraries.

Toolkit

Qt toolkit includes different tools for development, such as: 1. Qt Creator - IDE for development, debugging and deployment of application 2. Qt Designer - part of Qt Creator, tool for graphical design of UI 3. Qt Linguist - tool used for internationalization of application. Mainly, every can be easily build and deployed without these tools by using different IDEs or editors, but I would encourage you to try out Qt Creator cause it is nicely tuned for Qt projects.

4 Chapter 1. Introduction CHAPTER 2

Getting started with Qt

This part will explain how to install Qt and how to create your first projectin Qt Creator

Prerequisites

Before we proceed, let’s install some packages we may need in order to build and debug our applications.

Linux

Linux users need few additional packages like: 1. OpenGL - open graphics library for hardware-accelerated rendering 2. GNU Make - a tool which controls the generation of executables and other non-source files of a program 3. GCC - GNU Compiler Collection 4. gdb - GNUdebugger You can install these packages using following command: sudo apt-get install gcc g++ gdb make libgl1-mesa-dev

Note: The command above will only work in Debian-like distributions, such as Ubuntu, Linux Mint, KDE Neon, etc.

Windows

No additional software must be installed. Everything should work out of box.

5 qtlabs Documentation, Release

MacOS

No idea, honestly.

Qt installation

Let’s first start with installation of Qt and proceed with trying it out by creating a simple hello world project:

Note: Installation will use approx. 1.47GiB of disk space.

1. Go to Qt download page and download Qt by picking open source version.

2. After downloading the installer run it. Linux users need to add permission for execution. For that, right click on the file -> Properties -> set flag ‘is executable’, than it should become executable.

6 Chapter 2. Getting started with Qt qtlabs Documentation, Release

3. You can skip creating a Qt account or, obviously, create one.

4. Choose the path you would like to install Qt

2.2. Qt installation 7 qtlabs Documentation, Release

5. On selecting components page pick the latest version of Qt (5.9.1 at the moment) and Tools.

8 Chapter 2. Getting started with Qt qtlabs Documentation, Release

6. Install it! If everything went good, you shall be able to start Qt Creator. Now, let’s set up the build configuration.

Setting up the build configuration

Before you can start using Qt you need to ensure that the build configuration isset properly. Long story short, config- uration includes selection of a compilerand a version Qt libraries. A combination of these two components (compiler and Qt version) is called a kit and is a corner stone of cross-compilation. Butwe will get back to it later. Now you ony need to check if the default kit isworking fine. To do that: 1. Start Qt creator.

2.2. Qt installation 9 qtlabs Documentation, Release

2. Go to Tools -> Options...

3. Select Build & Run in the menu on the left, then pick tab Kits, and check ifthere is an Auto-detected kit. If there is one, select it and check if both C and C++ compilers are set. If both are set, it means that your kit is properly set and you can skip the rest of this part and start with your first project.

4. If no kit is auto-detected or if auto-dected kit misses Qt version or compilers, you have to set them up manually.

5. To set up Qt version go to Qt versions tab -> Add... ,go to the Qt installation path and search for file inside that folder. It should be somewhere inside a folder like 5.9/gcc_64/bin or else depending on the platform and version used.

10 Chapter 2. Getting started with Qt qtlabs Documentation, Release

6. To set up compilers go to Compilers tab -> Add, select the proper compiler that you use (usually MinGW for Windows and GCC for Linux) and search for gcc and g++ in the system.

2.2. Qt installation 11 qtlabs Documentation, Release

After just click ok and that is it! You are ready for your first project!

First project in Qt Creator

Before we start with learning Qt we should first learn how to create and maintain the project in Qt creator: 1. Open Qt Creator, go to the Welcome page, and click Projects -> New Project

2. Since we want to check if everything is working fine, we pick Application and click next

3. Give a name and place for a project. It is always a nice idea to store all projects in one place, so you can create a workspace and mark it as a default project location.

12 Chapter 2. Getting started with Qt qtlabs Documentation, Release

4. Pick a minimal version of Qt libraries. Since we don’t really care about compatability so far, you can leave it as it is. But we also won’t use Qt Designer this time, so unmark “With ui. file”.

2.3. First project in Qt Creator 13 qtlabs Documentation, Release

5. Pick a kit to use. Most probably you will only have one kit, thus you have not so many options. But interesting part is hidden in details. Here you can define a place and a name for a building directory. By default it is located on the same level as the project folder, but you can choose any other level or a foldr name, it should not bring you any troubles except a warning. You can also see that there three possible versions: debug, release, and progile. You can freely use any of them, the differnce is only that debugging and profiling versions add some information to executable for debugging/profiling.

14 Chapter 2. Getting started with Qt qtlabs Documentation, Release

6. Finish the creation After finishing the creation Creator will open the project and show main.qml file. On the left side you can see the structure of a project. It include .pro file, you won’t usually change, it is just specifies Qt modules used in the project and sources and headers. Then the project has sources and headers sections. Since we don’t have any headers in our project, so you shall only be able to see the Sources section. Next, there is a resource section. We will later talk about what resources are, but long story short those are collections of files that will be included into executable, so later on you will only need to put one file in the target machine for deployment instead of bunch of pictures and conf files. You can see that main.qml represents some basic “hello world”-like template. Let’s change it now for something just a bit fancier to get to know how to add files to a project. Let it be clocks, for example. First update the main.cpp and main.qml files. Replace the contents ofmain.qml with following lines: import QtQuick 2.6 import QtQuick.Window 2.2

Image { visible: true id: background source: "pics/clocks_background.png"

Image { id: minuteArrow

2.3. First project in Qt Creator 15 qtlabs Documentation, Release

source: "pics/clocks_minute_arrow.png" x: parent.width/2 - minuteArrowRotation.origin.x y: parent.height/2 - minuteArrowRotation.origin.y

transform: Rotation { id: minuteArrowRotation origin.x: minuteArrow.width/2 origin.y: minuteArrow.height - minuteArrow.width/2

Behavior on angle { RotationAnimation { duration: 400; direction:

˓→RotationAnimation.Clockwise} } } }

Image { id: hourArrow source: "pics/clocks_hour_arrow.png" x: parent.width/2 - width/2 y: parent.height/2 - height + width/2

transform: Rotation { id: hourArrowRotation origin.x: hourArrow.width/2 origin.y: hourArrow.height - minuteArrow.width/2

Behavior on angle { RotationAnimation { duration: 400; direction:

˓→RotationAnimation.Clockwise} } } }

Timer { interval: 60000 repeat: true running: true triggeredOnStart: true onTriggered: { var today = new Date() hourArrowRotation.angle = ((today.getHours()%12) * 30) minuteArrowRotation.angle = today.getMinutes() * 6 } } }

QML may now look a bit weird, but later yu will see that it is very useful when implementing GUI. Next, open main.cpp file and replace its contents with next lines:

16 Chapter 2. Getting started with Qt qtlabs Documentation, Release

#include #include int main(int argc, char *argv[]) { QGuiApplication app(argc, argv);

QQuickView view; view.setSource(QUrl(QStringLiteral("qrc:/main.qml")));

view.setFlags(Qt::FramelessWindowHint| Qt::WindowStaysOnBottomHint); view.setX(1150); view.setY(20); view.setColor(QColor(Qt::transparent)); view.show();

return app.exec(); }

No we need to add to the project images that we are going to use in the project. You can download pics from github qtlabs repo in src/firstproject/pics. Create a new directory called pics inside the project and put the downloaded pics into that folder. Now you need to add them to a project resources. To add new files to resources right click on qml.qrc -> Add existing... and choose all pics you need (hold Ctrl or Shift for multi-picking). Adding sources is similiar to adding resources, you only need to right click on sources or headers and add new or existing files.

Note: To add a file to a project right click on any section (folder) of the project -> Add new(add existing..) To add file to a project right click on the .qrc file -> Add new(add existing..) To delete file from a project right on the file -> Remove

From now on you should be able to run your first app. Click Run in the bottom corner. Your application shall run as a bottom window, so hide other windows to check it out. Our application has frameless window, so in order to close it just click Stop button in Qt creator above Application output section. Congratulations! You have just finised your first app. Try now just to tune it a bit: 1. Clock arrows move to slow. Try to find a way to make the minute arrow act like a second arrow and the hour arrow act like a minute arrow

Hint: Search main.qml for the answer

2. Why should our app run on the bottom? Let’s move it to foreground!

Hint: You should probably delete something in main.cpp

2.3. First project in Qt Creator 17 qtlabs Documentation, Release

18 Chapter 2. Getting started with Qt CHAPTER 3

Lab 1. Qt basics

This chapter will guide you through corner stones of C++ based application development using Qt. We will start with overview of typical main.cpp file for Qt project, then proceed with contents of C++ based Qt basic modules, such as QtCore, QtGui, and QtWidgets. Later on we will look at QObject class, which is the corner stone of Qt.

Typical main.cpp file

Let’s first look at the example of main.cpp:

1 #include

2 #include

3 4 int main(int argc, char** argv) 5 {

6 QApplication app(argc, argv);

7 QLabel("Hello world!");

8 lbl.show();

9 return app.exec();

10 }

You can see now that it is lot like any other C++ program’s main file. It goes as following: 1. Declare inclusions. These can be user headers as well as precompiled Qt libraries, if any Qt classes are used directly in main function. In the above we use QLabel and QApplication, thus we declare them before using in main(). 2. Create an instance of QApplication class. This object controls and maintains the application that we create. Only one instance of QApplication is allowed in one program. 3. Create an instance of QLabel. After creating Qt elements are usually invisible, so we have to call show() in order to make it visible. In this case QLabel object is the root object, which means that it will be created as an separate window, and the applicaion will exit once this window is closed. 4. Last line launches the execution of the application, which runs till the moment QApplication::exit() is called.

19 qtlabs Documentation, Release

Note: Try to create two instances of QLabel inside one application. Are they shown in separate windows? If so, will the application exit if you close one of them? Now try to set the first label as a parent for the second label. Refer to QLabel members list. What happens now? Are both labels shown in one window?

Qt basic modules

Qt library includes more than 500 classes, which cover the most part of OS functionality. But no worries, you don’t have remeber them all. Due to nice modulariztion you only need to have an idea in mind of which module can include functionality you need, and then go through module classes list in search of a relevant class. Any Qt based program must include one or few of following modules: QtCore, QtGui, QtWidgets, QtQuick, QtQML.

Note: Some of modules above will only work in combination with others. For instance, QtQuick is used along with QtQML module.

In the previous excersise you got in touch with some Qt classes, namely QApplication and QLabel. Let’s now list Qt basic C++ modules and specify the example classes those modules include: Module Declaration in .pro Description and classes included

QtCore core Set of basic classes not related to GUI • containers: QList, QVector, QMap, QVariant • io classes: QIODevice, QFile • timers: QTimer • date and time: QDate, QTime • events: QEvent • settings: QSettings • animation: QAbstractAnimation • QCoreAppication • QObject, a corner stone of any Qt class • multi-threading/processing: QThread, QProcess QtGui gui Set of classes for window system integration, OpenGL integration, pallette and cursor shape handling, etc. • QWindow • QGuiApplication, inherits QCoreApplication QtWidgets widgets Includes widget classes, building blocks for GUI • QWidget, the basic class for any widget • indication: QLabel, QLCDNumber • layout: QHBoxLayout, QVBoxLayout

20 Chapter 3. Lab 1. Qt basics qtlabs Documentation, Release

• buttons: QPushButton, QCheckButton • scrolls: QSlider, QScrollBar • input: QLineEdit, QSpinBox • pics: QImage, QPixmap • painting: QPainter, QBrush, QPen

QObject model philosophy

QObject is a base class for almost each class in Qt. But what is exactly hidden in it? First of all, QObject class is respnosble for creating hyerarchical model in application, what allows developer not to care about maintaing the memory while creating and deleting objects. You can pass the parent for an object as a parameter on creation:

QObject(QObject* parentObject=0)

As you can see, default value for this parameter is zero, so if you can skip it if you want to create a root object. Another way to set the parent is to call setParent() function. But what do we need parent-children relationship for? Let’s look at the short example:

QObject* obj1= new QObject; QObject* obj2= new QObject(obj1); QObject* obj3= new QObject(obj2); QObject* obj4= new QObject(obj1);

You can see that hyerarchy for the program above goes as follows:

Now, if we call deleteLater() method of obj3 or obj4, it will only delete obj3 or obj4 respectivly. In contrast, if we call obj2.deleteLater() it will delete obj2 along with obj3. Finally, if we call obj1.deleteLater() we will destroy all four objects. Thus, calling deleteLater() method deletes the instance and all its children.

Note: Usually, every object in Qt application should be created by calling new and deleted with deleteLater()

3.3. QObject model philosophy 21 qtlabs Documentation, Release method. Excptions are objects with no parents or temporal objects, like objetc that were created to be passed as an argument, for instance lbl.setPixmap(QPixmap(":/background.png")), where QPixmap object is used as an argument for setPixmap function and does not even have a name.

But it’s not the only reason why we need parent concept. You can access the list of children from object by calling children(), or you can search for specific child using findChild() function. For widgets parent-children relation looks even more interesting. Every child widget can be only rendered inside its parent. For instance, following example shows two QPushButton objects created on top of QLabel:

QLabel* lbl= new QLabel; lbl->setPixmap(QPixmap(":/background.png"));

QPushButton* pb1= new QPushButton("Button 1", lbl); QPushButton* pb2= new QPushButton("Button 2", lbl); pb2->move(pb1->width(),0);

It makes the answer for the previous excersice obvious. Since both widgets did not have a parent, they both were created as separate windows.

Signals and slots

Last and the most important about QObject is the signal-slot connection feature. The concept of signals and slots is very simple and that is why it is so good: 1. Every object of class inherited from QObject can transimit and receive signals. 2. Every object of class inherited from QObject can have one or few slots. Slot is a function that is called when a signal connected to it is received. 3. Every signal can be connected to one or few slots, internal(signal and slot are inside one object) and external (signal and slot are in different objects). 4. Each signal can have one or few argumentsthat will be passed to the slot. 5. Signal and slot connection can be performed in any part of the program. 6. When one objectstaking part in connetion is destructed, signal and slot are automatically disconnected. Of course, there are few issues of using signal-slot mechanism: 1. There is no compiling-time checking of connect() function, so if something is wrong with connect() you will only be able to see it after starting the application. 2. Signal-slot connection works a bit slower than direct call of function. You won’t see it, probably, but still it is good to know. 3. by default signal-slot connection works in queued way, which means that some time will pass between emiting a signal and calling a dedicated slot. 4. Class that utilizes signals and slots must be inherited from QObject or one of QObject successors.

22 Chapter 3. Lab 1. Qt basics qtlabs Documentation, Release

Signals

Signals in Qt is nothing but functions with the capability of sending messages. Signals are always public in Qt5, Which means that you can emit signals that are defined in predecessor class as well as you can emit signal that you have defined by yourself.To create and use a signal: 1. Put Q_OBJECT macro in header file right below the opening bracket like this: class MyClass: public QObject { Q_OBJECT

2. Declare the signal in class in signals section: signals: void mySignal(int arg1);

Note: Arguments you want to pass to slot should be specified inside backets, not as a return value.

3. Whenever you want to emit the signal, just call emit: int a= 10; emit mySignal(a);

Here you emit mySignal() with 10 as an argument. Later on you will see that almost anything can be used as an argument, what makes it especially usefull when using object pointers as arguments.

Slots

Slot in Qt is a function that can be called if the dedicated signal is triggered. Still, slots can also be called as a normal function. Moreover, slots can be public, protected or private, just like a normal function. To create a slot: 1. Put Q_OBJECT macro in header file right below the opening bracket like this: class MyClass: public QObject { Q_OBJECT

2. Declare the slot in class in public slots, protected slots or private slots section: public slots: void mySlot(int arg1);

3. Define the slot in .cpp just like a regular function: void MyClass::mySlot(int arg1) { int a= arg1+ 10; qDebug()<<"the answer is"<< a; }

Note: Here qDebug() function is used to print the answer in the console, you can think of it as analouge of printf().

The only thing left is to connect mySlot() to some signal, so it will be called every time signal is triggered.

3.3. QObject model philosophy 23 qtlabs Documentation, Release

Signal-slot connetion

Connection between signals and slots is performed using connect(). Normally, you use it like this:

MyClass* obj1= new MyClass; MyClass* obj2= new MyClass; QObject::connect(obj1, SIGNAL(mySignal(int)), obj2, SLOT(mySlot(int)));

Note: As mentioned above, you call connect() from any part of the program. Nevertheless, you should add QObject:: before connect() if you try to use it outside of class inherited from QObject, for instance, in main().

Arguments of connect() are: • sender: pointer to the sender object; • signal: pointer to the signal function (you can see it is inside the SIGNAL() macro) • receiver: pointer to the receiver object; • slot: pointer to the slot function (you can see it is inside the SLOT() macro)

Note: If you call connect() inside a class and want to use it as the receiver or the sender, you can use this pointer instead

So that is it! Every time mySignal() of obj1 is triggered mySlot() of obj2 is called. Later on, if you want to disconnect these signal and slot you only need to call disconnect function: After that, obj2 will no longer react on mySignal() of obj1. Only few more notes about connections left: 1. Signal can be connected to other signals. If so, signal that used a slot will be emitted every time the first signal is emitted. 2. Signal and slot that are connected to each other should have the same number of arguments. The only exception is when slot does not have any arguments at all.

Conclusion and exercise

Thus, we have discussed basic principles of Qt. It is a good alternative to classic implementation of connection between component, even though it brings some overheads. QObject is a base class for almost each class in Qt. It is used to create a hyerarchical model, automatic memory management, and for realization of signal-slot model. Signals and slots help objects to communicate with each other. Signals can be connected to few slots, as well slot can be connected to few signals. Slot function is called whenever the dedicated signal is triggered.

Exercise

Let’s create this time a image viewer. It will show pics from a specified folder. It should has a label that will show an image and two buttons: “Next” and “Previous”, that will change the current image. Few hints on how to do it, although you can have a better idea of implementation: 1. Create Qt widget application project. 2. Create a class inherited from QWidget.

24 Chapter 3. Lab 1. Qt basics qtlabs Documentation, Release

3. Add one QLabel and two QPushButtons as attributes of this class.

Note: You at look previos examples to refresh memories, or check out QPushButton and QLabel documentation to see a bit more about these classes.

4. Implement a function, that would set up the path for viewer’s directory

Note: Please, check out QString class documentaion. It is a common class used for strings in Qt.

5. Implement slots, that will set next and previos image in the folder as the current pixmap for our label.

Hint: QDir is the class of choice for you. It has a function operator [] which returns the name of a file at the position specified inside the brackets, for instance:

QDir dir("/home/user"); QString fileName= dir[1]; will return the name of the second file in “/home/user directory”

6. Connect signals of your buttons to dedicated slots you have created. 7. Create an instance of your calss in main(). Good luck!

3.4. Conclusion and exercise 25