anda_skoa
20-02-2003, 18:53
Lektion 6: Einfache GUI
Autor: anda_skoa
Diese Lektion zeigt, wie man mehrere Widgets in einem übergeordneten Widget zusammenfassen kann.
Außerdem wird gezeigt, wie man die Funktionalität der Widgets benutzt.
Erst mal wieder unsere Dateien:
lektion6.pro
TEMPLATE = app
CONFIG += qt thread warn_on
SOURCES = lektion6.cpp qttutwidget.cpp
HEADERS = qttutwidget.h
TARGET = lektion6
MOC_DIR = mocs
OBJECTS_DIR = obj
Die letzten beiden Zeilen sind neu. Sie weisen qmake an, zwei Verzeichnisse als Ablageort für bestimmte Nebenprodukte des Erstellungsprozesses zu benutzen.
Das MOC_DIR enthält dann die von MOC, dem Qt Meta Object Compiler, generierten Dateien.
Das OBJECTS_DIR enthält die vom Compiler erzeugten Object Dateien (.o Dateien).
Diese Maßnahme hält das Projektverzeichnis sauberer.
lektion6.cpp
#include <qapplication.h>
#include "qttutwidget.h"
int main( int argc, char* argv[] )
{
QApplication app( argc, argv );
QtTutWidget tutwidget( 0 );
tutwidget.resize( 200,30 );
app.setMainWidget( &tutwidget );
tutwidget.show();
return app.exec();
}
Bis auf minimale Änderungen identisch mit lektion5.cpp
qttutwidget.h
#ifndef QTTUTWIDGET_H
#define QTTUTWIDGET_H
#include <qwidget.h>
class QLineEdit;
class QtTutWidget : public QWidget
{
Q_OBJECT
public:
QtTutWidget(QWidget* parent=0, const char* name=0);
protected slots:
void slotButtonClicked();
protected:
QLineEdit* m_lineEdit;
};
#endif
Unser Widget ist nun direkt von QWidget abgeleitet. Es muss diesmal kein spezielles Aussehen haben, da wir es nur als Container für die anderen Widgets benutzen.
class QLineEdit;
Eines dieser Widget ist ein QLineEdit (http://doc.trolltech.com/3.0/qlinedit.html). Wir haben in unserem Hauptwidget einen Pointer auf eine Instant dieser Klasse, darum müssen wir den Typ hier bekannt machen (forward declaration).
Q_OBJECT
Unser Widget besitzt einen Slot und muss darum mit dem Q_OBJECT Makro markiert werden.
Diese Markierung führt dazu, dass qmake beim Erstellen des Makefiles eine Regel für den MOC und diese Datei erstellt.
Der MOC generiert dann Code, der für die Signal/Slot Benutzung wichtig ist.
Fehlt dieses Makro, dann ist unser Slot nur eine normale Methode.
protected slots:
void slotButtonClicked();
Hier deklarieren wir einen parameterlosen Slot.
Wie bei Methoden kann es public, protected und private Slots geben.
Der Name der Methode ist egal, wir haben hier jedoch "slot" als Namensteil gewählt, um in der CPP Datei leichter erkennen zu können, dass wir es mit einem Slot zu tun haben.
protected:
QLineEdit* m_lineEdit;
Deklarierung eines QLineEdit Pointers.
QWidget Instanzen werden normalerweise immer mit new am Heap erzeugt, liegen also als Pointer vor.
Ein QLineEdit ist ein einzeiliges Texteingabefeld.
qttutwidget.cpp
#include <qpushbutton.h>
#include <qlineedit.h>
#include <qlayout.h>
#include <qmessagebox.h>
#include "qttutwidget.h"
QtTutWidget::QtTutWidget(QWidget* parent, const char* name)
: QWidget(parent, name)
{
QLayout* layout = new QHBoxLayout(this);
m_lineEdit = new QLineEdit(this);
QPushButton* button = new QPushButton("Hier klicken", this);
layout->add(m_lineEdit);
layout->add(button);
QObject::connect(button, SIGNAL(clicked()), this, SLOT(slotButtonClicked()));
}
void QtTutWidget::slotButtonClicked()
{
QString text = m_lineEdit->text();
if (text.stripWhiteSpace().isEmpty()) return;
QMessageBox::information(this, "Wichtig", text);
}
Die CPP Datei unseres Widgets ist nun viel kürzer als in der letzten Lektion, dafür gibt es mehr #include Direktiven:
#include <qpushbutton.h>
#include <qlineedit.h>
#include <qlayout.h>
#include <qmessagebox.h>
qpushbutton.h kennen wir ja bereits.
qlineedit.h ist die Headerdatei für unseren QLineEdit.
qlayout.h ist eine Headerdatei, die verschiedene Layoutklassen deklariert.
Qt verfügt über einen einfachen, aber sehr effektiven Layouting Mechanismus, der die Größe von Widgets zur Laufzeit verändern kann, um die Sichtbarkeit der Wigdetinhalte zu gewährleisten.
Wir verwenden in hier, um uns nicht weiter um die Positionen der Widgets in unserem Containerwidget kümmern zu müssen.
Das Layout wird sicher stellen, dass beide Kindwidgets sichtbar sind und sich nicht überlappen.
qmessagebox.h ist der Header der Klasse QMessageBox (http://doc.trolltech.com/3.0/qmessagebox.html).
Diese Klasse kann für kleine Meldungen und Rückfragen benutzt werden, die dann vom Benutzer bestätigt werden müssen.
QtTutWidget::QtTutWidget(QWidget* parent, const char* name)
: QWidget(parent, name)
Da wir nun von QWidget ableiten, benutzen wir natürlich auch diesen Konstruktor.
QLayout* layout = new QHBoxLayout(this);
Hier ezeugen wir ein QHBoxLayout (http://doc.trolltech.com/3.0/qhboxlayout.html).
Ein HBoxLayout ordnet die Widget in diesem Layout horizontal an.
Als Parameter bekommt sein Konstruktor das Widget, für dessen Layout es zuständig ist, also in diesem Fall unser Containerwidget.
m_lineEdit = new QLineEdit(this);
QPushButton* button = new QPushButton("Hier klicken", this);
Wir erzeugen unsere beiden Widgets und geben als Parentwidget unser Containerwidget an.
Das hat zur Folge, dass sie gelöscht werden, wenn unser Widget gelöscht wird. Darum brauchen wir keine
delete Aufrufe im Destruktor unseres Widgets.
Den Pointer auf den Button brauchen wir hier nur im Konstruktor, darum haben wir im Gegensatz zum LineEdit eine lokale Variable gewählt.
layout->add(m_lineEdit);
layout->add(button);
Wir geben die beiden Widgets in unser Layout. Zuerst den LineEdit, denn er soll links vom Button sein.
Wäre das Layout ein VBoxLayout, dann wäre der LineEdit über dem Button.
QObject::connect(button, SIGNAL(clicked()), this, SLOT(slotButtonClicked()));
Wir verbinden das clicked() Signal des Buttons mit unserem Slot.
void QtTutWidget::slotButtonClicked()
{
Der Slot sieht in der CPP Datei wie eine normale Methode aus und kann auch wie eine normale Methode aufgerufen werden.
In unserem Fall wird er Slot über den Signal/Slot Mechanismus von Qt aufgerufen, wann immer der Button geklickt wird.
QString text = m_lineEdit->text();
Wir holen uns den Text, der gerade im LineEdit steht uns speichern ihn in einer lokalen Variable.
if (text.stripWhiteSpace().isEmpty()) return;
Hier prüfen wir, ob der Text leer ist.
Eigentlich würde isEmpty() reichen, aber wir wollen auch keine Eingaben zulassen, die nur aus Leerzeichen bestehen, darum entfernen wir alle Leerzeichen vom Anfang und vom Ende des Textes, bevor wird die Prüfung machen.
Falls der Text leer ist, kehren wir aus der Funktion zurück.
QMessageBox::information(this, "Wichtig", text);
Für die Standardfälle brauchen wir selbst keine QMessageBox anzulegen, denn Trolltech hat dafür ein paar statische Methoden vorbereitet, die wir nur noch mit den nötigen Parametern aufrufen müssen.
Hier verwenden wir information, was in einer MessageBox mit einem Rufzeichen-Icon und einem OK Button resultiert.
Als Fenstertitel setzen wir "Wichtig" und als Text unseren LineEdit Inhalt.
Erzeugung
Wie auch in den letzten Lektionen mit qmake und make.
Experimente
- Experimentieren mit HBoxLayout und VBoxLayout.
- Beobachten des Layoutings beim Verändern der Fenstergröße mit der Maus.
- Ausprobieren verschiedener static Methoden von QMessageBox.
-----------------
Vielleicht kann jemand von den anderen Qt Entwicklern hier als Lektion 7 das selbe Beispiel mit Hilfe von Qt Designer machen.
Also Widget mit LineEdit und Button, H-Layout.
Davon QtTutWidget ableiten und die Änderungen im Ctor zeigen.
Ciao,
_
Autor: anda_skoa
Diese Lektion zeigt, wie man mehrere Widgets in einem übergeordneten Widget zusammenfassen kann.
Außerdem wird gezeigt, wie man die Funktionalität der Widgets benutzt.
Erst mal wieder unsere Dateien:
lektion6.pro
TEMPLATE = app
CONFIG += qt thread warn_on
SOURCES = lektion6.cpp qttutwidget.cpp
HEADERS = qttutwidget.h
TARGET = lektion6
MOC_DIR = mocs
OBJECTS_DIR = obj
Die letzten beiden Zeilen sind neu. Sie weisen qmake an, zwei Verzeichnisse als Ablageort für bestimmte Nebenprodukte des Erstellungsprozesses zu benutzen.
Das MOC_DIR enthält dann die von MOC, dem Qt Meta Object Compiler, generierten Dateien.
Das OBJECTS_DIR enthält die vom Compiler erzeugten Object Dateien (.o Dateien).
Diese Maßnahme hält das Projektverzeichnis sauberer.
lektion6.cpp
#include <qapplication.h>
#include "qttutwidget.h"
int main( int argc, char* argv[] )
{
QApplication app( argc, argv );
QtTutWidget tutwidget( 0 );
tutwidget.resize( 200,30 );
app.setMainWidget( &tutwidget );
tutwidget.show();
return app.exec();
}
Bis auf minimale Änderungen identisch mit lektion5.cpp
qttutwidget.h
#ifndef QTTUTWIDGET_H
#define QTTUTWIDGET_H
#include <qwidget.h>
class QLineEdit;
class QtTutWidget : public QWidget
{
Q_OBJECT
public:
QtTutWidget(QWidget* parent=0, const char* name=0);
protected slots:
void slotButtonClicked();
protected:
QLineEdit* m_lineEdit;
};
#endif
Unser Widget ist nun direkt von QWidget abgeleitet. Es muss diesmal kein spezielles Aussehen haben, da wir es nur als Container für die anderen Widgets benutzen.
class QLineEdit;
Eines dieser Widget ist ein QLineEdit (http://doc.trolltech.com/3.0/qlinedit.html). Wir haben in unserem Hauptwidget einen Pointer auf eine Instant dieser Klasse, darum müssen wir den Typ hier bekannt machen (forward declaration).
Q_OBJECT
Unser Widget besitzt einen Slot und muss darum mit dem Q_OBJECT Makro markiert werden.
Diese Markierung führt dazu, dass qmake beim Erstellen des Makefiles eine Regel für den MOC und diese Datei erstellt.
Der MOC generiert dann Code, der für die Signal/Slot Benutzung wichtig ist.
Fehlt dieses Makro, dann ist unser Slot nur eine normale Methode.
protected slots:
void slotButtonClicked();
Hier deklarieren wir einen parameterlosen Slot.
Wie bei Methoden kann es public, protected und private Slots geben.
Der Name der Methode ist egal, wir haben hier jedoch "slot" als Namensteil gewählt, um in der CPP Datei leichter erkennen zu können, dass wir es mit einem Slot zu tun haben.
protected:
QLineEdit* m_lineEdit;
Deklarierung eines QLineEdit Pointers.
QWidget Instanzen werden normalerweise immer mit new am Heap erzeugt, liegen also als Pointer vor.
Ein QLineEdit ist ein einzeiliges Texteingabefeld.
qttutwidget.cpp
#include <qpushbutton.h>
#include <qlineedit.h>
#include <qlayout.h>
#include <qmessagebox.h>
#include "qttutwidget.h"
QtTutWidget::QtTutWidget(QWidget* parent, const char* name)
: QWidget(parent, name)
{
QLayout* layout = new QHBoxLayout(this);
m_lineEdit = new QLineEdit(this);
QPushButton* button = new QPushButton("Hier klicken", this);
layout->add(m_lineEdit);
layout->add(button);
QObject::connect(button, SIGNAL(clicked()), this, SLOT(slotButtonClicked()));
}
void QtTutWidget::slotButtonClicked()
{
QString text = m_lineEdit->text();
if (text.stripWhiteSpace().isEmpty()) return;
QMessageBox::information(this, "Wichtig", text);
}
Die CPP Datei unseres Widgets ist nun viel kürzer als in der letzten Lektion, dafür gibt es mehr #include Direktiven:
#include <qpushbutton.h>
#include <qlineedit.h>
#include <qlayout.h>
#include <qmessagebox.h>
qpushbutton.h kennen wir ja bereits.
qlineedit.h ist die Headerdatei für unseren QLineEdit.
qlayout.h ist eine Headerdatei, die verschiedene Layoutklassen deklariert.
Qt verfügt über einen einfachen, aber sehr effektiven Layouting Mechanismus, der die Größe von Widgets zur Laufzeit verändern kann, um die Sichtbarkeit der Wigdetinhalte zu gewährleisten.
Wir verwenden in hier, um uns nicht weiter um die Positionen der Widgets in unserem Containerwidget kümmern zu müssen.
Das Layout wird sicher stellen, dass beide Kindwidgets sichtbar sind und sich nicht überlappen.
qmessagebox.h ist der Header der Klasse QMessageBox (http://doc.trolltech.com/3.0/qmessagebox.html).
Diese Klasse kann für kleine Meldungen und Rückfragen benutzt werden, die dann vom Benutzer bestätigt werden müssen.
QtTutWidget::QtTutWidget(QWidget* parent, const char* name)
: QWidget(parent, name)
Da wir nun von QWidget ableiten, benutzen wir natürlich auch diesen Konstruktor.
QLayout* layout = new QHBoxLayout(this);
Hier ezeugen wir ein QHBoxLayout (http://doc.trolltech.com/3.0/qhboxlayout.html).
Ein HBoxLayout ordnet die Widget in diesem Layout horizontal an.
Als Parameter bekommt sein Konstruktor das Widget, für dessen Layout es zuständig ist, also in diesem Fall unser Containerwidget.
m_lineEdit = new QLineEdit(this);
QPushButton* button = new QPushButton("Hier klicken", this);
Wir erzeugen unsere beiden Widgets und geben als Parentwidget unser Containerwidget an.
Das hat zur Folge, dass sie gelöscht werden, wenn unser Widget gelöscht wird. Darum brauchen wir keine
delete Aufrufe im Destruktor unseres Widgets.
Den Pointer auf den Button brauchen wir hier nur im Konstruktor, darum haben wir im Gegensatz zum LineEdit eine lokale Variable gewählt.
layout->add(m_lineEdit);
layout->add(button);
Wir geben die beiden Widgets in unser Layout. Zuerst den LineEdit, denn er soll links vom Button sein.
Wäre das Layout ein VBoxLayout, dann wäre der LineEdit über dem Button.
QObject::connect(button, SIGNAL(clicked()), this, SLOT(slotButtonClicked()));
Wir verbinden das clicked() Signal des Buttons mit unserem Slot.
void QtTutWidget::slotButtonClicked()
{
Der Slot sieht in der CPP Datei wie eine normale Methode aus und kann auch wie eine normale Methode aufgerufen werden.
In unserem Fall wird er Slot über den Signal/Slot Mechanismus von Qt aufgerufen, wann immer der Button geklickt wird.
QString text = m_lineEdit->text();
Wir holen uns den Text, der gerade im LineEdit steht uns speichern ihn in einer lokalen Variable.
if (text.stripWhiteSpace().isEmpty()) return;
Hier prüfen wir, ob der Text leer ist.
Eigentlich würde isEmpty() reichen, aber wir wollen auch keine Eingaben zulassen, die nur aus Leerzeichen bestehen, darum entfernen wir alle Leerzeichen vom Anfang und vom Ende des Textes, bevor wird die Prüfung machen.
Falls der Text leer ist, kehren wir aus der Funktion zurück.
QMessageBox::information(this, "Wichtig", text);
Für die Standardfälle brauchen wir selbst keine QMessageBox anzulegen, denn Trolltech hat dafür ein paar statische Methoden vorbereitet, die wir nur noch mit den nötigen Parametern aufrufen müssen.
Hier verwenden wir information, was in einer MessageBox mit einem Rufzeichen-Icon und einem OK Button resultiert.
Als Fenstertitel setzen wir "Wichtig" und als Text unseren LineEdit Inhalt.
Erzeugung
Wie auch in den letzten Lektionen mit qmake und make.
Experimente
- Experimentieren mit HBoxLayout und VBoxLayout.
- Beobachten des Layoutings beim Verändern der Fenstergröße mit der Maus.
- Ausprobieren verschiedener static Methoden von QMessageBox.
-----------------
Vielleicht kann jemand von den anderen Qt Entwicklern hier als Lektion 7 das selbe Beispiel mit Hilfe von Qt Designer machen.
Also Widget mit LineEdit und Button, H-Layout.
Davon QtTutWidget ableiten und die Änderungen im Ctor zeigen.
Ciao,
_