Aus LinuxUser 12/2001

Adventskalender mit C++ und Qt (Seite 2)

for bild in *.gif; do
 convert -geometry 64x64 $bild `basename $bild gif`xpm
 done
convert -geometry 64x64  tuer.gif tuer.xpm

Dieses kleine Shell-Skript geht der Reihe nach alle Dateien mit der Endung .gif durch und skaliert sie auf maximal 64×64 Pixel herunter (die Proportionen bleiben dabei erhalten, sodass ein Bild, das höher als breit ist, mit einer Höhe von 64 Pixeln, aber einer geringeren Breite herauskommt). Gleichzeitig wandelt convert das Ergebnis dank entsprechender Dateiendungsangabe ins xpm-Format um und legt es unter dem alten Dateinamen, aber mit der Endung .xpm statt .gif ab.

Wer sich eine so entstandene XPM-Datei einmal anschaut, sieht schnell, warum sich dieses Format gut zum Programmieren in C(++) eignet:

static char *magick[] = { […] }

Das Bild liegt bereits als Zeiger (*) auf ein Feld (Array) ([]) vom Datentyp char („character“ – (druckbares ASCII-)Zeichen) vor. Liest man das entsprechende File mit #include in eine Quellcode-Datei ein, kann man ihn unter dem Namen magick sofort ansprechen. Allerdings mag Qt XPMs lieber als Konstanten, weshalb static char * in static const char* zu ändern wäre. Zudem dürfen natürlich nicht alle 25 Zeiger magick heißen – besser wäre etwa bild_dateiname (z. B. bild_1 bis bild_24 und bild_tuer). Das lässt sich mit sed und einem kleinen Shell-Skript erledigen:

for file in *.xpm; do
 sed -e "s/char \*magick/const char\* bild_`basename $file .xpm`/" $file > _$file
 mv _$file $file
 done

sed ersetzt das erste Auftreten von char *magick in einer Zeile durch const char* bild_ plus den Dateinamen des aktuell bearbeiteten Files ohne die Dateiendung .xpm. Der Zeiger in der Datei 1.xpm wird so in bild_1 umbenannt. Da das Sternchen in derlei regulären Ausdrücken eine Sonderbedeutung hat, muss es durch ein \ geschützt werden. Die veränderten Daten landen in einer temporären Datei _originalDateiname.xpm, mit der anschließend die Originaldatei überschrieben wird (mv).

Türchen und andere Objekte

Nach diesen Vorbereitungen heißt es, sich um das Programm selbst zu kümmern. Moderne GUI-Programmierung orientiert sich am Paradigma der Objektorientierung. Welche Objekte brauchen wir also? Neben dem obligatorischen Anwendungsobjekt ein Hauptfenster, das wiederum aus 24 Türchen besteht. Diese unterscheiden sich nur unwesentlich, nämlich in der Aufschrift und dem dahinter versteckten Bildchen. Es wäre also albern, 24 mal nahezu identischen Code zu schreiben. Stattdessen bauen wir eine Klasse namens Tuerchen, die all das in sich vereint, was bei Türchen-Objekten identisch ist. Die Unterschiede legen wir erst fest, wenn wir ein individuelles Objekt dieser Klasse erzeugen.

Das Erzeugen geht selbstverständlich nicht aus dem Nichts, sondern mit einer speziellen Funktion, dem Konstruktor der Klasse, den es in einer Datei mit der Endung .cpp („Cplus plus“) zu implementieren gilt. Der Konstruktor heißt immer genauso wie die Klasse selbst, in unserem Fall also Tuerchen(). Als Funktion kann er Argumente mit auf den Weg bekommen. Das bietet sich an, denn die einzelnen Türchen-Objekte dürfen gleich bei ihrer „Geburt“ erfahren, welches Bild sie enthalten und für welchen Tag sie gedacht sind:

Tuerchen::Tuerchen( QPixmap* bildchen, const int tag )

Der String Tuerchen vor dem :: besagt, dass der Konstruktor Tuerchen() zur Klasse Tuerchen gehört. Dabei übergeben wir das Bildchen nicht etwa als Zeiger auf ein char-Feld, wie es in den xpm-Dateien definiert ist, sondern als Zeiger auf eine QPixmap, eine spezielle Qt-Klasse, die die Arbeit mit Pixmaps erleichtert.

Damit unsere Tuerchen-Objekte die Vorteile von Qt-GUI-Objekten genießen, müssen sie selbst welche sein. Das geht ganz einfach mit Vererbung: Wir definieren, dass sich Tuerchen die Eigenschaften einer Qt-Widget-Klasse „einverleibt“. Da es im Qt-Werkzeugkasten keine bereits passende Klasse gibt, leiten wir Tuerchen von der allgemeinen Qt-Widget-Klasse QWidget ab:

: QWidget( elternwidget, name )

Hilfe!

Der QWidget-Konstruktor hätte gern zwei Argumente, doch woher wissen wir das? Keine Hexerei, denn zum Glück gibt es die API-Dokumentation zu Qt, die sich in HTML-Form unter /usr/doc/qt(2)/html/, /usr/share/doc/packages/qt/html/ o. ä. im besten Fall bereits auf dem eigenen Rechner findet. Wer Qt aus RPMs eingespielt hat, muss aufpassen: Viele Distributoren lagern die Dokumentation in Extra-Pakete (qt2-examples, qt2-tutorial und qt2-doc-html bei Caldera, qt-devel-doc bei SuSE) aus. Sofern man ständig online ist, kann man den Web-Browser auch auf http://doc.trolltech.com/ richten; für unsere Zwecke reicht die Qt-2.3.1-Dokumentation unter http://doc.trolltech.com/2.3/.

Dort finden wir unter dem Punkt API Reference die Alphabetical Class List, wo unter dem Buchstaben W ein Link auf die Dokumentation zu QWidget zeigt. Als erste öffentliche (public) Funktion ist der Konstruktor QWidget aufgeführt; ein Klick darauf bringt uns zur näheren Beschreibung (Abbildung 3).

Abbildung 3: Hilfe zum QWidget-Konstruktor
Abbildung 3: Hilfe zum QWidget-Konstruktor

Dieser Konstruktor hätte gern drei Argumente, wobei alle ignorieren kann, wer mit dem Standardwert 0 zufrieden ist. Unsere Tuerchen-Objekte sollen jedoch keine Hauptfenster werden, wie die Null des parent-Arguments festlegt, sondern zu einem Adventskalender-Objekt gehören. Einen Zeiger auf dieses Elternfenster wollen wir also bei der Geburt eines Tuerchens mit übergeben. Namenlos soll das Baby auch nicht sein: Zwar werden wir die im zweiten Argument angegebene „Widget-ID“ nie verwenden, doch guter Programmierstil ist ihre Festlegung schon.

Da der name eines Widgets möglichst eindeutig sein soll, legen wir ihn besser beim Erstellen eines Türchen-Objekts als Argument des Tuerchen-Konstruktors fest. Und warum sollten wir nicht die Flexibilität behalten, auch das Eltern-Widget bei der Tuerchen-Geburt festzulegen? Der komplette „Fußabdruck“ (footprint) des Tuerchen-Konstruktors sieht dann so aus:

Tuerchen::Tuerchen( QWidget* elternwidget, QPixmap* bildchen,
                 const int tag, const char* name )
         : QWidget( elternwidget, name ){}

Mit den Zeigern elternwidget und name werden wir nichts weiter anstellen – da soll sich QWidget drum kümmern.

Bekanntmachung

Damit andere Objekte, etwa der Adventskalender selbst, wissen, wie sie Tuerchen erzeugen (und was sie sonst noch damit anstellen können), müssen sie über die Schnittstellen (API, „Application Programmers‘ Interface“) der Tuerchen-Klasse aufgeklärt werden. Diese schreibt man in eine Header-Datei, die sich mit der #include-Direktive leicht dort einlesen lässt, wo sie gebraucht wird. Darin steht, …

LinuxUser 12/2001 KAUFEN
EINZELNE AUSGABE Print-Ausgaben Digitale Ausgaben
ABONNEMENTS Print-Abos Digitales Abo
TABLET & SMARTPHONE APPS
Deutschland

Hinterlasse einen Kommentar

  E-Mail Benachrichtigung  
Benachrichtige mich zu: