Dear Readers!
In this post I’d like to share how to change between an older and newer coding style while creating a Qt widgets application. It is not a big deal really, but I found both of these styles circulating, and though the older one is easier to understand, it requires a bit more typing. The newer style on the other hand requires a bit less typing, but is also a bit more obscure where exactly the classes are coming from. To make things clear and easy to transition between these styles, here’s a small comparison for them.
The code snippet below shows us the header file of the older style, where a forward declaration of the MainWindow class is seen within the Ui namespace, just as well as a private pointer to it inside the class. The rest of the code is pretty standard and doesn’t change between styles, so I’ll just omit the discussion of those.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// mainwindow.h with old style ui access
#include <QMainWindow>
// ...
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
// ...
private:
Ui::MainWindow *ui;
// ...
};
If we check the source file, we immediately see an include of “ui_mainwindow.h”, which is a header that does not exist anywhere in our project source folders, and yet it is still a valid include. It is so, because Qt’s UIC will generate it for us from the .ui file, once we press the compile button.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// mainwindow.cpp file using old style ui access
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->graphicsView->setScene(&scene);
// ...
}
MainWindow::~MainWindow()
{
delete ui;
}
The other thing to be noticed is the creation of a MainWindow instance in the constructor with the new operator and a non-empty destructor, following the good old RAII idiom. All this is required to create a window out of a .ui file, and to access any widget one might place onto this window, one needs to use the ui pointer and the associated member access operator, just as seen in the example above.
This looks pretty straightforward, but using ui->xyz for all widget access can get pretty tedious after a while, but fortunately for us, some of this tedium can be shaved off by using the newer style (which is also the default style in Qt Creator nowadays). In order to do that, one needs to transfer the aforementioned “ui_mainwindow.h” include to the header, then get rid of the MainWindow forward declaration and ui pointer alltogether. Next, we need to inherit from Ui::MainWindow in a private fashion, but be careful about the order of inheritance: It is supposed to be invariant, but as discussed in one of my eariler posts, it really isn’t, so make sure that inheritance from QMainWindow stays in the first position. The rest of the header stays the same, so here’s how it looks like after these changes:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// mainwindow.h for accessing ui elements without ui pointer
#include "ui_mainwindow.h"
#include <QMainWindow>
// ...
class MainWindow : public QMainWindow, private Ui::MainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
// ...
private:
// ...
};
The source file from now on basically corrects itself: since there is no ui pointer anymore, we can get rid of the new Ui::MainWindow in the constructor, and we can empty the destructor as well (if we didn’t have anything else in there). Finally, we need to remove all ui and access operators, and simply use all widgets by their names, as if they were part of the class itself (which they are, since we inherited from Ui::MainWindow). One must remember though, that by removing all the ui instances, the members did not stop being pointers, so the access operator for pointers must still be used, just as seen below with the setScene() function.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// mainwindow.cpp file without ui pointer.
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
{
setupUi(this);
graphicsView->setScene(&scene);
// ...
}
MainWindow::~MainWindow()
{
}
That is all for now, thanks for reading.