Learn Qt

Teaching Qt® to the world!

Flower

Disecting Your First Application

Last time, you installed QtCreator and then generated your first application. It everything worked out ok, you should now have your very own, completely empty QMainWindow on the screen. That is all great, but what did you really do? Let’s go through the generated code so that you understand what really happened.

Your very first Qt application.

Your very first Qt application.

The application consists of one class and a main function to get everything going. Let’s start by having a look at the main function show below.

main.cpp

#include <QtGui/QApplication>
#include "mainwindow.h"

int main(int argc, char *argv[])
{
  QApplication a(argc, argv);
  MainWindow w;
  w.show();
  return a.exec();
}

What it does is that is creates an instance of QApplication. Every Qt application needs one, and only one, QApplication instance. It represents the application it self and contains the main event-loop.

fact-logoWhat is an event-loop? you might ask. It is just what it sounds like – a loop waiting for events. For instance keyboard presses, mouse activity, network packages, timer event, etcetera. The event-loop collectes these events and passes them to the appropriate receiver. This could be the widget in focus, a QTcpSocket instance waiting for a package, a QTimer object, and so on. This means that you do not have to write a loop waiting for events, instead, you let Qt handle it and pass it to your objects.

When the QApplication has been created, a MainWindow is created. This is your class – we’ll look at it later on. The MainWindow is then shown before the exec method of the application is called. When calling exec, the event-loop is entered and the application comes to life.

So, what about the MainWindow class? The entire class declaration is show below, but lets focus on one part at a time.

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QtGui/QMainWindow>

namespace Ui
{
  class MainWindowClass;
}

class MainWindow : public QMainWindow
{
  Q_OBJECT

public:
  MainWindow(QWidget *parent = 0);
  ~MainWindow();

private:
  Ui::MainWindowClass *ui;
};

#endif // MAINWINDOW_H

The header file starts with the inclusion of the base class, QMainWindow, and the forward declaration of the Ui::MainWindowClass.

fact-logoForward declarations is a way to tell the C++ compiler that there is a class with a name. We can use this name to define pointers, but not to work with the class itself. When working with the class, we must first include the actual class declaration. How can we define pointers to a class that has not been properly declared then? All pointers are the same size (one memory address), so the compiler can still allocate enough memory for it regardless of what it points to. And what’s the point? We don’t have to include a reference to another headerfile in our header file. This saves opening a file and parsing it when compiling, thus improving build time performance.

When the inclusions and forward declarations are done our class, the MainWindow, is declared. It inherits QMainWindow and has a constructor, a destructor and a pointer to a member ui, of the type Ui::MainWindowClass. Nothing odd about this. The constructor makes it possible to pass a parent widget to our class. One more thing, the first line of the class declaration contains the macro Q_OBJECT. We will look closer at this in a later blog post. For now, just remember that it is important to have it there as soon as you inherit QObject directly or indirectly (QMainWindow inherits QWidget that inherits QObject – you can find this just at the top of the documentation page for each class, the line starting with “Inherits…”).

So, over the the MainWindow implementation. The first couple of lines are just includes the MainWindow header file and the ui_mainwindow.h header file. The latter contains the Ui::MainWindowClass class. The file is actually generated from the mainwindow.ui file that we will look at later on. To give you the big picture, the .ui file is created by “painting” the user interface visually. This is where that design enters the code so that you can actually do something with it.

mainwindow.cpp – part 1

#include "mainwindow.h"
#include "ui_mainwindow.h"

After the includes follows the constructor and destructor. All they do is that they create and delete the ui member variable. The constructor also passes its arguments to the parent class and calls ui->setupUi, passing itself (this) to the function as an argument. This creates the designed user interface inside the MainWindow.

mainwindow.cpp – part 2

MainWindow::MainWindow(QWidget *parent)
  : QMainWindow(parent), ui(new Ui::MainWindowClass)
{
  ui->setupUi(this);
}

MainWindow::~MainWindow()
{
  delete ui;
}

So, finally, I spoke of painting the user interface, creating the .ui file. Try double clicking the mainwindow.ui file in the QtCreator file list. This will show you something like the view below. This is the Designer view of QtCreator, where you can drag, drop and fiddle around with your user interface designs.

The Designer view of QtCreator.

The Designer view of QtCreator.

Actually getting a design in place and making it do something is what we will look at in the next installment. Hope to see you then!

Leave a Reply

You must be logged in to post a comment.