Zusammengesetzte Widgets erstellen

Bis jetzt haben wir immer ein „Container-Widget“ erstellt, das lediglich dazu diente, ein Layout anzuwenden und angezeigt zu werden. Leitet man eine Klasse von QWidget ab und wendet im Konstruktor darauf ein Layout an, erhält man ein zusammengesetztes Widget. Dieses kann dann wie ein Standard-Widget angezeigt oder abermals in ein Layout aufgenommen werden. Dadurch kann man Einheiten im GUI abkapseln und auch mehrfach verwenden.

Als Beispiel wollen wir aus unserer Widget-Gruppe zur Authentifizierung einen eigenen Widget-Typ erstellen:

AuthWidget.h
#ifndef AUTHWIDGET_H
#define AUTHWIDGET_H
 
#include <QWidget>
#include <QGroupBox>
#include <QPushButton>
#include <QLineEdit>
#include <QVBoxLayout>
 
class AuthWidget : public QWidget
{
 
  public:
    AuthWidget();
    ~AuthWidget();
 
  private:
    QPushButton *connectButton;
    QLineEdit *addressLineEdit, *usernameLineEdit, *pwLineEdit;
    QGroupBox *authBox;
    QVBoxLayout *layout, *authLayout;
 
};
 
#endif // AUTHWIDGET_H
AuthWidget.cpp
#include "AuthWidget.h"
#include <QApplication>
 
AuthWidget::AuthWidget()
{
  connectButton = new QPushButton( "Verbinden" );
  addressLineEdit = new QLineEdit();
  usernameLineEdit = new QLineEdit();
  pwLineEdit = new QLineEdit();
  authBox = new QGroupBox( "Authentifizierung erforderlich" );
  layout = new QVBoxLayout();
  authLayout = new QVBoxLayout();
 
  // Anstatt eine Verbindung herzustellen, beendet unser Button das Programm
  // 'qApp' ist ein globaler Zeiger auf unsere QApplication-Instanz, die im
  // 'QApplication'-Header deklariert ist.
  connect( connectButton, &QPushButton::clicked, qApp, &QApplication::quit );
 
  // Passwort beim Tippen nicht anzeigen
  pwLineEdit->setEchoMode( QLineEdit::Password );
  // Widget-Gruppe kann aktiviert werden
  authBox->setCheckable( true );
  authBox->setChecked( false );
 
  // Widgets in den Layouts platzieren
  authLayout->addWidget( usernameLineEdit );
  authLayout->addWidget( pwLineEdit );
  authBox->setLayout( authLayout );
  layout->addWidget( addressLineEdit );
  layout->addWidget( authBox );
  layout->addWidget( connectButton );
 
  setWindowTitle( "Verbinden" );
  setLayout( layout );
}
 
 
AuthWidget::~AuthWidget()
{
  delete connectButton;
  delete addressLineEdit;
  delete usernameLineEdit;
  delete pwLineEdit;
  delete authLayout;
  delete authBox;
  delete layout;
}

Dieses Widget können wir jetzt instanzieren und anzeigen:

main.cpp
#include "AuthWidget.h"
#include <QApplication>
 
int main( int argc, char *argv[] )
{
  QApplication app( argc, argv );
  AuthWidget w;
 
  w.show();
 
  return app.exec();
}

Das Ergebnis ist das gleiche wie vorhin, wir können diesen Widget-Typ aber immer wieder verwenden, ohne ihn aufwändig neu zu erstellen.

Wir können dieses Widget aber auch weiter verschachteln, um z.B. ein Widget zu erstellen, in dem man zusätzlich das Protokoll auswählen kann:

ConnectionWidget.h
// ConnectionWidget.h
#ifndef CONNECTIONWIDGET_H
#define CONNECTIONWIDGET_H
 
#include "AuthWidget.h"
#include <QComboBox>
#include <QVBoxLayout>
 
class ConnectionWidget : public QWidget
{
 
  public:
    ConnectionWidget();
    ~ConnectionWidget();
 
  private:
    AuthWidget *authWidget;
    QComboBox *protocolBox;
    QVBoxLayout *layout;
 
};
 
#endif // CONNECTIONWIDGET_H
ConnectionWidget.cpp
#include "ConnectionWidget.h"
 
ConnectionWidget::ConnectionWidget()
{
  authWidget = new AuthWidget();
  protocolBox = new QComboBox();
  layout = new QVBoxLayout();
 
  protocolBox->addItem("FTP");
  protocolBox->addItem("SSH");
  protocolBox->addItem("SMB");
 
  layout->addWidget( protocolBox );
  layout->addWidget( authWidget );
  setLayout( layout );
 
  setWindowTitle( "Verbinden" );
}
 
 
ConnectionWidget::~ConnectionWidget()
{
  delete authWidget;
  delete protocolBox;
  delete layout;
}
main.cpp
#include <QApplication>
#include "ConnectionWidget.h"
 
int main( int argc, char *argv[] )
{
  QApplication app( argc, argv );
  ConnectionWidget w;
 
  w.show();
 
  return app.exec();
}

Nun haben wir folgendes Ergebnis: