Advanced  Services Der GuiBuilder des QtCreators Back Next Up Home

Im Gegensatz zu den vorigen beiden Kapiteln legen wir kein leeres Qt Projekt an. Wir wählen jetzt eine Qt-Gui-Anwendung. Wir können nach dieser Entscheidung wählen zwischen einer Qt-Gui-Anwendung ohne Formdatei oder einer Qt-Gui-Anwendung mit Formdatei.


Qt-Gui-Anwendung ohne Formdatei

Eine Qt4-Gui-Anwendung ohne Formdatei ist ein mit einem Skelett angereichertes "leeres Qt Projekt". Es wird eine leere Klasse MainWindow angelegt, die von QMainWindow erbt und das Q_OBJECT Makro einbindet.

qt-projekt-ohne-form-1.jpg

qt-projekt-ohne-form-2.jpg

qt-projekt-ohne-form-3.jpg

qt-projekt-ohne-form-4.jpg

Man beachte, daß im obigen Screenshot die Checkbox zu "Form-Datei generieren" nicht angehakt ist.

qt-projekt-ohne-form-5.jpg

qt-projekt-ohne-form-6.jpg

Code in der Datei mainwindow.h
/*
mainwindow.h
*/
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QtGui/QMainWindow>

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = 0);
    ~MainWindow();
};
#endif // MAINWINDOW_H

Code in der Datei mainwindow.cpp
/*
mainwindow.cpp
*/
#include "mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
}

MainWindow::~MainWindow()
{

}

Code in der Datei main.cpp
/*
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();
}

Und so sieht das mit diesem Code erzeugte Fenter aus
qt-projekt-ohne-form-7.jpg

Wie bei einem leeren Qt-Projekt muß nun alles weitere von Hand codiert werden.



Qt-Gui-Anwendung mit Formdatei

Eine Qt-Gui-Anwendung mit Formdatei hat einen GuiBuilder, mit dem man die graphische Oberfläche entwerfen kann, indem man die QWidgets mit der Maus auf ein QMainWindow zieht.

qt-projekt-mit-form-1.jpg

qt-projekt-mit-form-2.jpg

qt-projekt-mit-form-3.jpg

Man beachte, daß die Checkbox zu "Form-Datei generieren" jetzt angehakt ist.

qt-projekt-mit-form-4.jpg

Beim Ausführen des Programms zeigt sich ein Fentser mit einer leeren Toolbar.

qt-projekt-mit-form-5.jpg


Übersicht über die angelegten Dateien

Es werden die folgende Codedateien angelegt:

Interessant sind die letzten beiden Dateien


mainwindow.ui

Klickt man auf mainwindow.ui, so schaltet der Qtcreator sofort auf die Designeransicht um. Klickt man in der linken Menüspalte auf Editieren, so kann man den Quelltext von mainwindow.ui einsehen. mainwindow.ui ist eine xml-Datei, in der die graphische Konfiguration, die der Benutzer mit dem Gui-Builder einrichtet festgehalten wird. Der Quelltext dieser Datei ist innerhalb des Qtcreators nicht editierbar. In der Theorie sollte das auch nicht notwendig sein.


ui_mainwindow.h

Beim Kompilieren wird aus mainwindow.ui die Headerdatei ui_mainwindow.h erzeugt. In diesem Header wird die Klasse Ui_MainWindow vereinbart, die sämtliche Komponenten enthält, die man mit dem Gui-Builder angelegt hat. Ui_MainWindow ist eine Toplevelklasse und leitet sich von keiner anderen gui-Klasse ab, im Gegensatz zu dem, was der Name vermuten läßt. Die mit Gui-Builder per drag und drop angelegten Komponenten werden als Zeiger in einem public Datenteil angelegt.

Des weiteren gibt es hier eine public inline-Methode

void setupUi(QMainWindow *MainWindow)

Hier wird nun wirklich ein Zeiger auf ein QMainWindow übergeben. und dieses MainWindow wird mit den Komponenten eingerichtet, die im Datenteil der Klasse Ui_MainWindow stehen. Hier sieht man zunächst noch nicht, woher das eigentliche QMainWindow kommt. In einem eigenen namespace Ui wird dann eine leere Klasse MainWindow angelegt, die public von Ui_MainWindow erbt. Man beachte, daß weder Ui_MainWindow noch Ui::MainWindow Klassen sind, die sich von QWidget ableiten !

namespace Ui
{
    class MainWindow : public Ui_MainWindow {};
}
// namespace Ui

Bei jedem Kompilierungsvorgang wird die Datei ui_mainwindow.h erneut aus der xml-datei mainwindow.ui generiert. Es nützt also nichts, sie von Hand zu bearbeiten. Sie ist deshalb auch im Projektfenster nicht sichtbar.


mainwindow.h

In mainwindow.h wird eine zweite Klasse MainWindow deklariert, die nun tatsächlich von QMainWindow erbt. Sie enthält im private Datenteil einen Zeiger ui vom Typ Ui::MainWindow*.


mainwindow.cpp

Das Interessante ist nun der Konstruktor der Klasse MainWindow. Er reicht zum einen natürlich das übergebene QWidget an den Elternkonstruktor weiter, initialisiert dann aber den Zeiger ui sozusagen on the fly durch einen Aufruf von new Ui::MainWindow. Dadurch kann im Rumpf des Konstruktors zu ui die Methode setupUi() aufgerufen werden. Ihr wird ein Zeiger auf das MainWindow-Objekt übergeben (nicht zu verwechseln mit Ui::MainWindow) und so richtet die Methode setupUi() die in Ui_MainWindow vereinarten Komponenten im MainWindow-Objekt ein:

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


Ein Beispiel mit zwei Buttons und einem Label

Mit drag und drop erzeugen wir folgendes Layout und versuchen uns dann im signal/slot Eventhandling



Signal/Slot Eventhandling

Es gibt mehrere Varianten um das Signal/Slot Eventhandling zu realisieren. Eine wichtige Rolle spielt dabei die Methode connect() aus QObject, die folgenden Aufbau hat:

QObject::connect(<SenderObjekt> , SIGNAL(<GesendetesEreignis()>), <Empfängerobjekt>, SLOT(<Reaktionsmethode()>));



Weg 1: Verwendung des "Signale und Slots" Fensters in der Designeransicht

Im Fenster unterhalb des Designers schalten wir von Aktionsansicht um auf Signale und Slots.

qt-signal-slot-fenster-01.jpg

Mit + erzeugt man eine neue Zeile im Signal/Slot-Fenster unterhalb des graphischen Entwurfs. Hier kann man die gewünschte Verbindung mit der Maus erzeugen, indem man sich die einzelen Objekte, die Signale und die Slots anzeigen läßt und dann auswählt.

qt-signal-slot-fenster-02.jpg

qt-signal-slot-fenster-03.jpg

qt-signal-slot-fenster-04.jpg

qt-signal-slot-fenster-05.jpg

Wir haben nun mit der Maus die folgende Codezeile erzeugt:

QObject::connect(exitButton, SIGNAL(clicked()), MainWindow, SLOT(close()));

Allerdings ist die obige Anweisung ein wenig versteckt. Sie wird in die Methode setupUi() eingefügt die sich (s.o.) in der nicht angezeigten Datei ui_mainwindow.h befindet.



Weg 2 : Aufruf der connect()-Methode in mainWindow.cpp selbst codieren

Es geht auch ohne Mausclicks. Stattdessen können wir diese Verbindung auch mit der Hand eintragen, indem wir sie in den Konstruktor von MainWindow in der Datei mainWindow.cpp legen, der Zugriff auf den Button muß dann dann über den zeiger ui erfolgen. Da die Methode setupUi() das Fenster einrichtet, muß der Aufruf von connect() nach dem von setupUi() kommen.

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    QObject::connect(ui->exitButton, SIGNAL(clicked(bool)), this, SLOT(close()));
}

Leider wird eine in mainwindow.h deklarierte und in mainwindow.cpp implementierte eigene slot-Methode auch nach dem Erstellen von Qtcreator nicht erkannt und deshalb auch nicht im Signal/Slot-Fenster angezeigt. Hier muß man einen anderen Weg wählen. Im Folgenden werden zwei Wege beschrieben.



Weg 3 : Mit F4 den Signal/Slot-Modus im QtCreator einschalten (siehe Screenshot)
qt-signal-slot-f4-01.jpg

qt-signal-slot-f4-02.jpg

qt-signal-slot-f4-03.jpg

Vom QtCreator wird nun in der xml-Datei mainwindow.ui der folgende Eintrag vorgenommen:

<connection>
   <sender>exitButton</sender>
   <signal>clicked()</signal>
   <receiver>MainWindow</receiver>
   <slot>close()</slot>
   ...


Weg 4 : Im Modus "Widgets bearbeiten" bleiben (bzw. mit F3 zurückwechseln)

Ist man (wieder) im Modus F3 (Widgets bearbeiten), so aktiviert man die betreffende Komponente, holt sich mit der rechten Maustaste das Kontextmenu und wählt "Slot anzeigen". Man erhält ein kleines Fenster mit dem Titel "Go to slot" und bestätigt die gewünschte Auswahl. Sodann wechselt QtCreator zur Datei mainwindow.cpp wo bereits eine Methode (in diesem Fall) mit dem Namen on_exitButton_clicked() erzeugt worden ist. Auch die Deklaration in der Headerdatei hat QtCreator erledigt. Man braucht lediglich den gewünschten Code einzutragen.

qt-signal-slot-context-01.jpg

qt-signal-slot-context-02.jpg

qt-signal-slot-context-03.jpg

Das close()-Ereignis müssen wir bei diesem Weg mit der Hand eintragen.

qt-signal-slot-context-04.jpg


Hinweis
qt-signal-slot-context-05.jpg


Signal/Slot Eventhandling, wenn keine slot-Methode existiert

In diesem Beispiel wollen wir zählen, wie oft der PushButton geklickt worden ist und diese Zahl auf dem Label erscheinen lassen. Für diesen Vorgang müssen wir die Reaktionsmethode selbst schreiben. Weg 4 von vorhin läßt sich sofort auf diese Situation übertragen und liefert uns die Reaktionsmethode on_pushButton_clicked().

qt-signal-slot-context-06.jpg

In mainwindow.h definieren wir eine private Variable countClicks und zählen Sie in der slot()-Methode hoch. Da auf einem QLabel nur Strings erscheinen können, konvertieren wir die int-Variable in einen QString.

qt-signal-slot-context-07.jpg
top Back Next Up Home