Search icon CANCEL
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Qt 5 and OpenCV 4 Computer Vision Projects

You're reading from   Qt 5 and OpenCV 4 Computer Vision Projects Get up to speed with cross-platform computer vision app development by building seven practical projects

Arrow left icon
Product type Paperback
Published in Jun 2019
Publisher Packt
ISBN-13 9781789532586
Length 348 pages
Edition 1st Edition
Languages
Tools
Arrow right icon
Author (1):
Arrow left icon
Zhuo Qingliang Zhuo Qingliang
Author Profile Icon Zhuo Qingliang
Zhuo Qingliang
Arrow right icon
View More author details
Toc

Table of Contents (11) Chapters Close

Preface 1. Building an Image Viewer 2. Editing Images Like a Pro FREE CHAPTER 3. Home Security Applications 4. Fun with Faces 5. Optical Character Recognition 6. Object Detection in Real Time 7. Real-Time Car Detection and Distance Measurement 8. Using OpenGL for the High-Speed Filtering of Images 9. Assessments 10. Other Books You May Enjoy

Setting up the full user interface

Let's proceed with the development. In the preceding section, we built a blank window and now we are going to add the menu bar, toolbar, image display component, and the status bar to the window.

First, instead of using the QMainWindow class, we will define a class ourselves, named MainWindow, which extends the QMainWindow class. Let's see its declaration in mainwindow.h:

    class MainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();

private:
void initUI();

private:
QMenu *fileMenu;
QMenu *viewMenu;

QToolBar *fileToolBar;
QToolBar *viewToolBar;

QGraphicsScene *imageScene;
QGraphicsView *imageView;

QStatusBar *mainStatusBar;
QLabel *mainStatusLabel;
};

Everything is straightforward. Q_OBJECT is a crucial macro provided by the Qt library. If we want to declare a class that has customized signals and slots of its own, or that uses any other facility from the Qt meta-object system, we must incorporate this crucial macro in our class declaration, or, more precisely, in the private section of our class, like we just did. The initUI method initializes all widgets that are declared in the private section. The imageScene and imageView widgets will be placed in the main area of the window to display images. Other widgets are self-explanatory from their type and name, so I will not say too much about them in order to keep the chapter concise.

To keep the chapter concise, I have not included each source file in the text in its entirety when I introduce it. For example, most of the time, the #include ... directions at the beginning of the files are omitted. You can refer to the source file in the code repository on GitHub to check the details if needed.

Another key aspect is the implementation of the initUI method in mainwindow.cpp as follows:

    void MainWindow::initUI()
{
this->resize(800, 600);
// setup menubar
fileMenu = menuBar()->addMenu("&File");
viewMenu = menuBar()->addMenu("&View");

// setup toolbar
fileToolBar = addToolBar("File");
viewToolBar = addToolBar("View");

// main area for image display
imageScene = new QGraphicsScene(this);
imageView = new QGraphicsView(imageScene);
setCentralWidget(imageView);

// setup status bar
mainStatusBar = statusBar();
mainStatusLabel = new QLabel(mainStatusBar);
mainStatusBar->addPermanentWidget(mainStatusLabel);
mainStatusLabel->setText("Image Information will be here!");
}

As you can see, at this stage, we don't create every item and button for the menu and toolbar; we just set up the main skeleton. In the preceding code, the imageScene variable is a QGraphicsSence instance. Such an instance is a container for 2D graphical items. According to its design, it only manages graphics items but doesn't have a visual appearance. In order to visualize it, we should create an instance of the QGraphicsView class with it, which is why the imageView variable is there. In our application, we use these two classes to display images.

After implementing all the methods of the MainWindow class, it's time to compile the sources. Before doing this, a number of changes need to be made to the ImageViewer.pro project file, as follows:

  1. We just write a new source file, and it should be known by qmake:
     # in ImageViewer.pro
SOURCES += main.cpp mainwindow.cpp
  1. The header file, mainwindow.h, has a special macro, Q_OBJECT, which indicates that it has something that cannot be dealt with by a standard C++ preprocessor. That header file should be correctly handled by a Qt-provided preprocessor named moc, the Meta-Object Compiler, to generate a C++ source file that contains some code relating to the Qt meta-object system. So, we should tell qmake to check this header file by adding the following line to ImageViewer.pro:
     HEADERS += mainwindow.h

OK. Now that all of that is complete, let's run qmake -makefile and make again, and then run the new executable. You should see the following window:

Well, so far so good. Now, let's go on to add the items that should appear in the menus as we intended. In Qt, each item in a menu is represented by an instance of QAction. Here, we take the action, which is to open a new image as an example. First, we declare a pointer to a QAction instance as a private member of our MainWindow class:

    QAction *openAction;

Then, in the body of the initUI method, we create the action as a child widget of the main window by calling the new operator, and add it to the File menu as follows:

    openAction = new QAction("&Open", this);
fileMenu->addAction(openAction);
You may notice that we create many Qt objects by calling the new operator, but never delete them. That is fine because all these objects are instances of QObject, or a subclass of it. Instances of QObject are organized in one or many object trees in the Qt library. When a QObject is created as the child of another object, the object will be added to its parent's children() list automatically. The parent object will take ownership of the child object. And, when the parent object is disposed of, its children will be deleted in its destructor automatically. In our application, we create most instances of QObject as children of the main window object, so we don't need to delete them.

Fortunately, buttons on the toolbar can also be represented by QAction, so we can add openAction directly to the file toolbar:

    fileToolBar->addAction(openAction);

As mentioned previously, we have seven actions to create: open, save as, exit, zoom in, zoom out, previous image, and next image. All of them can be added in the same way as we added the open action. Also, given that many lines of code are required to add these actions, we can do a little refactoring of the code—create a new private method named createActions, insert all the code of the action into that method, and then call it in initUI.

All actions are now created in a separate method, createActions, after the refactoring. Let's compile the sources and see what the window looks like now:

Great! The window looks just like the wireframe we designed, and we can now expand the menu by clicking on the items on the menu bar!

lock icon The rest of the chapter is locked
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at €18.99/month. Cancel anytime