QApplication and QMainWindow

Even though is possible using Qt in console mode, typically a Qt application has a graphic user interface.

That means that the event loop is managed by a QApplication instance, and the user interact with the application through widgets. As startup widget we could use any reasonable class derived from QWidget, but the normal choice fall on QMainWindow or, better, on a subclass of it that we create in our application.

Here we are going to see how it's easy to generate a main window for our application using Qt Creator.

Large part of the job is done by Qt Creator itself as we specify that we want to create a new project - Qt Gui Application, and specify that we want our MainWindow has QMainWindow as base class. Other possible alternatives here are QWidget and QDialog.

The standard main file generated by Qt Creator in this case is something like this:

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

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

return a.exec();
}

A QApplication object is instantiated, passing to it the arguments coming from the command line; and then a MainWindow object is created and showed. Finally the QApplication::exec() method is called, that would run the event loop manager.

This is already a working Qt GUI application, but let's add to it some minimal customization.
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <memory>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MainWindow(); // 1.

private:
MainWindow(const MainWindow&); // 2.
MainWindow& operator=(const MainWindow&);

void closeEvent(QCloseEvent* event); // 3.
std::auto_ptr<Ui::MainWindow> ui; // 4.
};

#endif // MAINWINDOW_H

1. I want MainWindow having always no ancestor, so I give no chance of passing to it a parent.
2. I don't want MainWindow to be copied, so I explicitely make unusable its copy ctor and assignment operator.
3. Let's add a check on the application end.
4. And let's be smart on the UI pointer, using an auto_ptr (no need for a more advanced smart pointer). In this way there is no need anymore for dtor in this class.

And here are the changes in the class implementation:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMessageBox>
#include <QCloseEvent>

MainWindow::MainWindow() : QMainWindow(NULL), ui(new Ui::MainWindow) // 1.
{
ui->setupUi(this);
}

void MainWindow::closeEvent(QCloseEvent* event) // 2.
{
int res = QMessageBox::warning(this, windowTitle(), "Are you sure?",
QMessageBox::Yes|QMessageBox::No);
if(res == QMessageBox::Yes)
event->accept(); // 3.
else
event->ignore(); // 4.
}

1. The QMainWindow ctor is called passing always NULL as parameter: no ancestor ever for objects of this class.
2. It's a virtual function defined in QWidget used to give the subclasses a chance to do so something when the user ask to close a window.
3. If the user confirms he wants to close the window, we mark the event as to be accepted.
4. The user changed his mind, we mark the event as to be ignored - the window won't be closed.

Besides this changes in the code, I made also a few changes in the GUI, using the internal Design Editor.

Firstly, I wanted "Simple App" be the title of my window. To do that, I selected MainWindow as current object in the Object Inspector (if you can't find it, check it in the menu Window - submenu View) and then, in the Property Editor I put the name I choose in the windowTitle field.

Secondly, I added a Menu, named File, with two items: Say Hello (currently doing nothing) and Exit (to close the window in an alternative way with respect to clicking on the 'X' on the window right top). This is done easily acting directly on the window as showed by the desing editor.

Thirdly, I wanted to associate a shortcut, Alt-X, to the Exit action. This could be done through the Action Editor window (if you don't see this windows, check the menu Window - submenu Views - Action Editor item). Double click on the item actionExit, it has been created for me by the Design Editor when I created the menu item Exit (by the way, I entered it as "E&xit" so that its x is interpreted as a shortcut in the menu) and you have access to all the details for the action. I was interested in adding a shortcut to it, so I entered it in the relative input line.

One more thing I wanted to do, was adding a connection between the Exit action and the window closing, so that clicking on the Exit menu item, or entering Alt-X, would actually close my window. I did that in the Signals & Slots Editor that should be accessible as a tabbed window besides the Action Editor. If you can't see it go in the menu Window - submenu Views - and check the relative item. I clicked on the big green plus to add a new connection, then I specified: actionExit as sender, triggered() as signal, MainWindow as receiver, and close() as slot.

If I get back to the Edit view (clicking on the Edit icon on the left in the Qt Creator window) I see the form as an XML file, in my case named mainwindow.ui, and I can check how the changes I made are reflected here.

No comments:

Post a Comment