Das große Ganze

24 dieser Tuerchen-Objekte wollen nun erschaffen und angeordnet werden – am besten in einem Objekt einer neuen Klasse Adventskalender, die das Hauptfenster stellt. Auch diese einfache Klasse, die lediglich einen Konstruktor besitzt, leiten wir von QWidget ab und schreiben ihr API in eine Datei namens adventskalender.h (Listing 1).

Listing 1

Adventskalender-API

adventskalender.h
#include <qwidget.h>
 class Adventskalender : public QWidget
 {
 public:
   Adventskalender( QWidget *elternwidget = 0,
       const char *name = "adventskalender" );
 };

adventskalender.cpp besteht aus gar nicht besonders viel Programmierung, sondern vor allem aus Festlegungen: Welche Bildchen sollen sich hinter den einzelnen Türchen verstecken, …

#include "1.xpm" // enthaelt bild_1[…]
 #include "24.xpm" // bild_24

für welchen Tag ist welcher Türcheninhalt gedacht, ….

static const char  bilder[24] = {
   bild_1, […], bild_24 };

… und an welchen x-y-Koordinaten soll das für einen bestimmten Tag gedachte Türchen stehen? (Die erste Spalte der ersten Zeile trägt die Koordinate 0,0.)

struct pos{
   int x;
   int y;
 } position[24] = {
   {1, 0}, // Position fuer Tuerchen Nr. 1[…]
   {2, 2}  // Nr. 24
 };

Im Adventskalender-Konstruktor legen wir zunächst ein unsichtbares sechsspaltiges und vierzeiliges Gitter fest, in dem die einzelnen Türchen "einrasten" sollen:

Adventskalender::Adventskalender( QWidget *elternwidget, const char *name )
                : QWidget( elternwidget, name )
 {
   QGridLayout * gitterraster = new QGridLayout( this, 6, 4,
                                    6, 4, "gitterraster" );

Bei den letzten drei Argumenten des QGridLayout-Konstruktors handelt es sich um die Randbreite (6), den Platz zwischen den Zellen (4 Pixel) und die Widget-ID des gitterraster-Zeigers. 24 Türchen erzeugen wir nun in einer for-Schleife, deren Körper innerhalb der geschweiften Klammern erst mit der Zählervariablen i gleich 1 bis hin zur 24 durchlaufen wird (i++ bedeutet, dass der Inhalt von i am Ende jeden Schleifendurchlaufs um eins erhöht wird):

for ( int i = 1; i <= 24; i++ ){
     QString name( "tuerchen" );
     name += QString::number(i);

Damit jedes Tuerchen-Objekt eine eigene ID bekommt, setzen wir sie in der Variablen name zusammen: Beim Türchen, das im ersten Schleifendurchlauf entsteht, lautet sie tuerchen1, beim letzten Durchlauf lautet name auf tuerchen24. name += Wert ist dabei eine Kurzform für name = name + Wert.

Nachdem wir die Tuerchen-API am Anfang der Datei mit #include "tuerchen.h" innerhalb der Adventskalender-Implementierung bekannt gemacht haben, können wir den public deklarierten Tuerchen-Konstruktor nun mit den Argumenten Eltern-Widget, Hintergrundbildchen, Aufschrift und ID aufrufen:

Tuerchen * tuer = new Tuerchen( this, new QPixmap( bilder[i-1] ), i, (const char *) name );

Mit bilder[i-1] holen wir uns dabei das an i-ter Stelle abgelegte XPM aus dem bilder-Array – da die Zählung bei Array-Elementen jedoch bei 0 beginnt, müssen wir als Index i-1 angeben. Indem wir es dem QPixmap-Konstruktor als Argument übergeben, erhalten wir ein passendes Pixmap-Objekt.

Zuletzt bauen wir das neue Tuerchen an passender Stelle ins Layout-Raster ein:

gitterraster->addWidget( tuer, position[i-1].x,
                                    position[i-1].y );
   }

Als Positionsangabe dient jeweils der x- und der y-Wert aus dem position-Element mit dem Index i-1. Tuerchen Nr. 24 wird damit an der Stelle (2,2) im Raster eingebaut.

Das gesamte Adventskalender-Widget färben wir jetzt (wie den Tuerchen-Pushbutton) grün ein und teilen dem Qt-Layout-Management außerdem mit, dass es eine feste, unveränderliche Größe haben soll. Diese berechnen wir jedoch nicht, sondern sagen mit sizeHint() einfach: "Nimm die Größe, bei der alle Teil-Widgets ideal platziert sind."

setBackgroundColor( QColor( 0, 155, 0 ) );
   setFixedSize( sizeHint() );
 }

Finale

Alle Widgets sind da, fehlt nur noch das Applikationsobjekt selbst. In der (allen C/C++-Programmen eigenen) Hauptfunktion main() (Listing 2) übergeben wir eventuelle Kommandozeilen-Optionen und Argumente (in unserem Fall prophylaktisch) an die eigentliche Applikation (argv enthält diese, argc ihre Anzahl). Das neue Adventskalender-Objekt wird in Zeile 8 zum Hauptfenster der Applikation, auf die app zeigt. Zeile 9 sorgt dafür, dass es auch auf dem Bildschirm erscheint, während Zeile 10 die sogenannte Anwendungsschleife startet: Das Adventskalender-Objekt beginnt zu leben. Sobald es geschlossen wird, bekommen wir von exec() einen Rückgabewert, und das Programm beendet sich.

Listing 2

Hauptroutine

advcal.cpp
1 #include <qapplication.h>
  2 #include "adventskalender.h"
  3
  4 int main( int argc, char  argv )
  5 {
  6   QApplication * app = new QApplication( argc, argv );
  7   Adventskalender * advcal = new Adventskalender();
  8   app->setMainWidget( advcal );
  9   advcal->show();
 10   return app->exec();
 11 }

Der Code ist geschrieben (und auf CD komplett nachzulesen) – wie wird daraus jetzt ein ausführbares Programm? Hiermit schlägt tmakes (oder qmakes) große Stunde: Aus einer einfachen Projektdatei, die alle selbstgeschriebenen Header-Dateien unter HEADERS, alle Implementierungsfiles unter SOURCES und den Namen der zu generierenden ausführbaren Datei unter TARGET angibt (Listing 3), wird mit

tmake -o Makefile advcal.pro

ein Makefile. Die CONFIG-Angaben release, qt und warn_on bedeuten, dass wir eine optimalisierte Qt-Applikation erstellen wollen, bei deren Übersetzung der Compiler mehr Warnungen ausgeben soll als üblich. Dass es sich beim Ergebnis um eine Anwendung (und nicht um eine Bibliothek) handelt, legt die TEMPLATE-Variable fest.

Listing 3

Projektdatei

advcal.pro
TEMPLATE = app
 CONFIG   = qt warn_on release
 HEADERS  = adventskalender.h \
            tuerchen.h
 SOURCES  = advcal.cpp \
            adventskalender.cpp \
            tuerchen.cpp
 TARGET   = advcal

Ein make sorgt dann hoffentlich für fehlerfreies Durchkompilieren – und ein ausführbares Binary namens advcal.

Glossar

GUI

"Graphical User Interface" – grafische Benutzerschnittstelle, der für Anwender/innen sichtbare Teil einer grafischen Applikation.

Compiler

Programm, das aus menschenlesbarem Quellcode ein maschinenlesbares ausführbares Binary macht.

Interpreter

Programm, das in einer Skript-Sprache geschriebenen Quellcode interpretiert und sofort ausführt.

Xlib

Die grundlegende Bibliothek, die alle zur Entwicklung einer X-Applikation nötigen (Low-Level-)Funktionen enthält.

basename

Dieses Kommando schneidet von einem Dateinamen, den es als erstes Argument bekommt, die Pfadangabe und ggf. die als zweites Argument angegebene Dateinamensendung ab. Aus tuer.gif in der Variablen bild wird so tuer., und da das basename-Kommando in `Backticks` eingeschlossen wurde, fügt die Shell dessen Ergebnis an deren Stelle ein. So wird letztlich folgendes Kommando ausgeführt:

static

Globale (also außerhalb einer Klasse oder Funktion deklarierte) statische Variablen sind außerhalb ihrer Datei (bzw. der, in die sie mit #include eingelesen wurden) unbekannt.

//

C++-Kommentarzeichen. Alles, was hinter ihm auf der Zeile steht, ignoriert der Compiler.

aufgedrückt

Operator ->, der die darauffolgende Funktion auf das Objekt anwendet, auf das ein Zeiger zeigt. Arbeitet man hingegen mit Objekten, die direkt in Variablen gespeichert sind, so heißt der entsprechende Operator . (Punkt).

LinuxCommunity kaufen

Einzelne Ausgabe
 
Abonnements
 

Related content

  • Adventskalender mit wxBasic
    Wer Silvester 2001 den guten Vorsatz fasste, im neuen Jahr endlich programmieren zu lernen, muss sich beeilen. Doch glücklicherweise sind Adventskalender dankbare Kandidaten, wenn es darum geht, eine überschaubare und nützliche Anwendung zu schreiben – dieses Jahr mit wxBasic.
  • Adventskalender in C++
    Wieder einmal steht die Adventszeit völlig unerwartet vor der Tür. Doch zum Glück zaubern Gideon und ein wenig C++ schnell einen hübschen KDE-Adventskalender für Freunde, Verwandte und Bekannte, während man selbst ein wenig programmieren lernt.
  • The Answer Girl
    Dass der Computeralltag auch unter Linux des Öfteren für Überraschungen gut ist, ist eher eine Binsenweisheit: Immer wieder funktionieren Dinge nicht oder nicht so, wie eigentlich angenommen. Das Answer-Girl im LinuxUser zeigt, wie man mit solchen Problemchen elegant fertig wird.
  • Programmieren mit Java und NetBeans
    Viele Computer-Liebhaber prägt eine Abneigung gegen herkömmliche Bastelei. Manche Menschen greifen mit Spaß zu Nadel und Faden, andere ziehen einen selbstprogrammierten Adventskalender vor. Wir geben eine Einführung in die Sprache Java [1] an Hand dieses Beispiels.
Kommentare

Infos zur Publikation

title_2014_08

Digitale Ausgabe: Preis € 5,95
(inkl. 19% MwSt.)

Mit der Zeitschrift LinuxUser sind Sie als Power-User, Shell-Guru oder Administrator im kleinen Unternehmen monatlich auf dem aktuelle Stand in Sachen Linux und Open Source.

Sie sind sich nicht sicher, ob die Themen Ihnen liegen? Im Probeabo erhalten Sie drei Ausgaben zum reduzierten Preis. Einzelhefte, Abonnements sowie digitale Ausgaben erwerben Sie ganz einfach in unserem Online-Shop.

NEU: DIGITALE AUSGABEN FÜR TABLET & SMARTPHONE

HINWEIS ZU PAYPAL: Die Zahlung ist auch ohne eigenes Paypal-Konto ganz einfach per Kreditkarte oder Lastschrift möglich!       

Tipp der Woche

Schnell Multi-Boot-Medien mit MultiCD erstellen
Schnell Multi-Boot-Medien mit MultiCD erstellen
Tim Schürmann, 24.06.2014 12:40, 0 Kommentare

Wer mehrere nützliche Live-Systeme auf eine DVD brennen möchte, kommt mit den Startmedienerstellern der Distributionen nicht besonders weit: Diese ...

Aktuelle Fragen

Server antwortet mit falschem Namen
oin notna, 21.07.2014 19:13, 0 Antworten
Hallo liebe Community, Ich habe mit Apache einen Server aufgesetzt. Soweit, so gut. Im Heimnet...
o2 surfstick software für ubuntu?
daniel soltek, 15.07.2014 18:27, 1 Antworten
hallo zusammen, habe mir einen o2 surfstick huawei bestellt und gerade festgestellt, das der nic...
Öhm - wozu Benutzername, wenn man dann hier mit Klarnamen angezeigt wird?
Thomas Kallay, 03.07.2014 20:30, 1 Antworten
Hallo Team von Linux-Community, kleine Zwischenfrage: warum muß man beim Registrieren einen Us...
openSUSE 13.1 - Login-Problem wg. Fehler im Intel-Grafiktreiber?
Thomas Kallay, 03.07.2014 20:26, 8 Antworten
Hallo Linux-Community, habe hier ein sogenanntes Hybrid-Notebook laufen, mit einer Intel-HD460...
Fernwartung für Linux?
Alfred Böllmann, 20.06.2014 15:30, 7 Antworten
Hi liebe Linux-Freunde, bin beim klassischen Probleme googeln auf www.expertiger.de gestoßen, ei...