In this section, we will build the image viewer application from scratch. No assumptions are made as to what integrated development environment (IDE) or editor you are using. We will just focus on the code itself and how to build the application using qmake in a Terminal.
First, let's create a new directory for our project, named ImageViewer. I use Linux and execute this in a Terminal, as follows:
$ pwd
/home/kdr2/Work/Books/Qt5-And-OpenCV4-Computer-Vision-Projects/Chapter-01
$ mkdir ImageViewer
$
Then, we create a C++ source file named main.cpp in that directory with the following content:
#include <QApplication>
#include <QMainWindow>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QMainWindow window;
window.setWindowTitle("ImageViewer");
window.show();
return app.exec();
}
This file will be the gateway to our application. In this file, we first include dedicated header files for a GUI-based Qt application provided by the Qt library. Then, we define the main function, as most C++ applications do. In the main function, we define an instance of the QApplication class, which represents our image viewer application while it is running, and an instance of QMainWindow, which will be the main UI window, and which we designed in the preceding section. After creating the QMainWindow instance, we call some methods of it: setWindowTitle to set the title of the window and show to let the window emerge. Finally, we call the exec method of the application instance to enter the main event loop of the Qt application. This will make the application wait until exit() is called, and then return the value that was set to exit().
Once the main.cpp file is saved in our project directory, we enter the directory in the Terminal and run qmake -project to generate the Qt project file, as follows:
$ cd ImageViewer/
$ ls
main.cpp
$ qmake -project
$ ls
ImageViewer.pro main.cpp
$
As you can see, a file named ImageViewer.pro is generated. This file contains
many directives and configurations of the Qt project and qmake will use this
ImageViewer.pro file to generate a makefile later. Let's examine that project file. Its content is listed in the following snippet after we omit all the comment lines that start with #, as follows:
TEMPLATE = app
TARGET = ImageViewer
INCLUDEPATH += .
DEFINES += QT_DEPRECATED_WARNINGS
SOURCES += main.cpp
Let's go through this line by line.
The first line, TEMPLATE = app, specifies app as the template to use when generating the project. Many other values are allowed here, for example, lib and subdirs. We are building an application that can be run directly, so the value app is the proper one for us. Using other values are beyond the scope of this chapter; you can refer to the qmake manual at http://doc.qt.io/qt-5/qmake-manual.html yourself to explore them.
The second line, TARGET = ImageViewer, specifies the name of the executable for the application. So, we will get an executable file named ImageViewer once the project is built.
The remaining lines define several options for the compiler, such as the include path, macro definitions, and input source files. You can easily ascertain which line does what based on the variable names in these lines.
Now, let's build the project, run qmake -makefile to generate the makefile, and then run make to build the project, that is, compile the source to our target executable:
$ qmake -makefile
$ ls
ImageViewer.pro main.cpp Makefile
$ make
g++ -c -pipe -O2 -Wall -W -D_REENTRANT -fPIC -DQT_DEPRECATED_WARNINGS -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -I. -I. -isystem /usr/include/x86_64-linux-gnu/qt5 -isystem /usr/include/x86_64-linux-gnu/qt5/QtGui -isystem /usr/include/x86_64-linux-gnu/qt5/QtCore -I. -isystem /usr/include/libdrm -I/usr/lib/x86_64-linux-gnu/qt5/mkspecs/linux-g++
-o main.o main.cpp
main.cpp:1:10: fatal error: QApplication: No such file or directory
#include <QApplication>
^~~~~~~~~~~~~~
compilation terminated.
make: *** [Makefile:395: main.o] Error 1
$
Oops! We get a big error. This is because, with effect from Qt version 5, all the native GUI features have been moved from the core module to a separate module, the widgets module. We should tell qmake that our application depends on that module by adding the line greaterThan(QT_MAJOR_VERSION, 4): QT += widgets to the project file. Following this modification, the content of ImageViewer.pro appears as follows:
TEMPLATE = app
TARGET = ImageViewer
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
INCLUDEPATH += .
DEFINES += QT_DEPRECATED_WARNINGS
SOURCES += main.cpp
Now, let's build the application again by issuing the qmake -makefile and make commands in the Terminal as follows:
$ qmake -makefile
$ make
g++ -c -pipe -O2 -Wall -W -D_REENTRANT -fPIC -DQT_DEPRECATED_WARNINGS -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -I. -I. -isystem /usr/include/x86_64-linux-gnu/qt5 -isystem /usr/include/x86_64-linux-gnu/qt5/QtWidgets -isystem /usr/include/x86_64-linux-gnu/qt5/QtGui -isystem /usr/include/x86_64-linux-gnu/qt5/QtCore -I. -isystem /usr/include/libdrm -I/usr/lib/x86_64-linux-gnu/qt5/mkspecs/linux-g++ -o main.o main.cpp
g++ -Wl,-O1 -o ImageViewer main.o -lQt5Widgets -lQt5Gui -lQt5Core -lGL -lpthread
$ ls
ImageViewer ImageViewer.pro main.cpp main.o Makefile
$
Hooray! We finally get the executable file, ImageViewer, in the project directory. Now, let's execute it and see what the window looks like:
As we can see, it's just a blank window. We will implement the full user interface as per our designed wireframe in the next section, Setting up the full user interface.
Although we didn't mention any IDE or editor and built the application in a Terminal with qmake, you can use any IDE with which you are familiar, for instance, Qt Creator. Especially on Windows, the terminal (cmd or MinGW) does not perform as well as Terminals on Linux and macOS, so please feel free to use an IDE.