Home / LinuxUser / 2001 / 12 / Adventskalender mit C++ und Qt

Newsletter abonnieren

Lies uns auf...

Folge LinuxCommunity auf Twitter

Top-Beiträge

Heftarchiv

LinuxUser Heftarchiv

EasyLinux Heftarchiv

Ubuntu User Heftarchiv

Ubuntu User Heftarchiv

Partner-Links:

Das B2B Portal www.Linx.de informiert über Produkte und Dienstleistungen.

Vorfreude, schönste Freude

Adventskalender mit C++ und Qt

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).

Tip a friend    Druckansicht Bookmark and Share
Kommentare

Hits
Wertung: 200 Punkte (22 Stimmen)

Schlecht Gut

Infos zur Publikation

Infos zur Publikation

LinuxUser 05/2014

Aktuelle Ausgabe kaufen:

Heft als PDF kaufen

LinuxUser erscheint monatlich und kostet in der Nomedia-Ausgabe EUR 5,95 und mit DVD EUR 8,50. Weitere Informationen zum Heft finden Sie auf der LinuxUser-Homepage.

Im LinuxUser-Probeabo erhalten Sie drei Ausgaben für 3 Euro. Das Jahresabo (ab EUR 60,60) können Sie im Medialinx-Shop bestellen.

Tipp der Woche

Bilder vergleichen mit diffimg
Bilder vergleichen mit diffimg
Tim Schürmann, 01.04.2014 12:40, 1 Kommentare

Das kleine Werkzeug diffimg kann zwei (scheinbar) identische Bilder miteinander vergleichen und die Unterschiede optisch hervorheben. Damit lassen sich nicht nur Rätsel a la „Orignial und Fäls...

Aktuelle Fragen

programm suche
Hans-Joachim Köpke, 13.04.2014 10:43, 8 Antworten
suche noch programme die zu windows gibt, die auch unter linux laufen bzw sich ähneln sozusagen a...
Funknetz (Web-Stick)
Hans-Joachim Köpke, 04.04.2014 07:31, 2 Antworten
Bei Windows7 brauche ich den Stick nur ins USB-Fach schieben dann erkennt Windows7 Automatisch, a...
Ubuntu 13.10 überschreibt immer Windows 8 Bootmanager
Thomas Weiss, 15.03.2014 19:20, 8 Antworten
Hallo Leute, ich hoffe das ich richtig bin. Ich habe einen Dell Insipron 660 Ich möchte gerne Ub...
USB-PTP-Class Kamera wird nicht erkannt (Windows-only)
Wimpy *, 14.03.2014 13:04, 15 Antworten
ich habe meiner Frau eine Digitalkamera, AGFA Optima 103, gekauft und wir sind sehr zufrieden dam...
Treiber
Michael Kristahn, 12.03.2014 08:28, 5 Antworten
Habe mir ein Scanner gebraucht gekauft von Canon CanoScan LiDE 70 kein Treiber wie bekomme ich de...