Programmierung unter Kde 2

Die Programmierung ist unter der KDE 2.2 Bibliothek um einiges für den Entwickler einfacher geworden. Man hat die Konzepte grundlegend umgestellt, um die Entwicklung von Desktop Anwendungen zu vereinfachen. Vieles ist automatisiert worden, um die Codierung in Grenzen zu halten.

...page...Seit Neustem ist KDE 2.2 der neuste Streich der KDE-Entwickler. Die Software Entwickler müsssen einige Änderungen in Kauf nehmen. Das KDE Team hat also ganze Arbeit geleistet. Etliche neue Klassen findet man in der KDE Library. Der Migrationsaufwand von KDE 1.X Applikationen ist aber eher als "marginal" zu bezeichnen.

Die Architektur
KDE 2.2 besteht nicht nur aus einer reinen GUI Bibliothek (KdeUI). Da KDE eine leistungsfähige Desktop Umgebung ist, basiert es auf einem Framework. Dieses stellt dem Entwickler verschiedene Utitlity Klassen für verschiedene Dienstleistungen bereit. Dies sind die KDE Dienste, das KDE Objekt Modell, die verschiedenen KParts, das KIO (Netzwerktransparenz), der KDE Daemon und die Core Klassen des Desktops. Um jedoch eine grafische Anwendung zu entwickeln, ist ein GUI Toolkit unerläßlich. Jedes Toolkit baut unter Linux intern auf die X-Window Schnittstelle auf. KDE 2.2 basiert ebenfalls noch auf dem Qt GUI Toolkit der norwegischen Firma Troll Tech. Auf der Basis dieser plattformübergreifende Bibliothek wurden innerhalb von KDE 2.2 weitere Widgets implementiert und die bestehenden Widgets entsprechend erweitert. Nur sind die KDE Klassen jetzt mehr an den Funktiktionalitäten des KDE Desktop angepasst. So erhält man noch leistungsfähigere Widgets. Der Einstieg in die Klassen ist nicht einfach, da eine Vielzahl neuer Widgets hinzugekommen sind. Eine Aufstellung einiger Widgets finden Sie in Tabelle#1 vor. Zur Entwicklung von KDE 2.2 Applikationen muß das Qt 2.3 Toolkit, der KDE Support und die KdeLibs installiert sein. Dies dürfte bei den meisten Distribution gegeben sein. Andernfalls sind die entsprechenden Pakete unter kde.org und trolltech.com herunterzuladen. Alles unterliegt der GPL (General Public Licence) und ist frei verfügbar.

((Qt.tiff))

@b:Mittels kpackage läßt sich nachprüfen, ob auch die aktuelle Qt (Version 2.3) installiert ist.

@yu:Tabelle#1:Einige Widgets aus der Bibliothek KdeUI
@y1:Widget Beschreibung
@y:KColorButton Ein Widget zur Auswahl einer Farbe
KContainerLayout Dies ist ein KDE Klasse zur Ausrichtung der Widgets
KEdit Diese ist für mehrzeiligen Eingaben gedacht
KFontDialog Hierüber läßt sich der Zeichensatz auswählen
KMsgBox Dies ist eine einfache Mitteilungsbox
KNoteBook Dies ist ein Dialog mit einzelnen Registereitern
KProgress Dies ist ein einfacher Fortschrittsbalken
KQuickHelpWindow Dient zur Anzeige von Hilfetexten
KStatusBar Eine einfache Statusleiste
KListBox Zeigt einzelne Listeneinträge in einer ListBox an
KTreeList Zeigt eine Liste in einer Baumstruktur an
KWizard Dies ist eine Klasse zur Erzeugung eines Wizards
KPushButton Dies ist eine einfache Schaltfläche
KMenuBar Dies ist eine einfache Menuleiste




@zk1:Interne Sicht auf KDE

@n:Der KDE Desktop ist ein wohl organisiertes Objekt Modell. Überall kommen C++ Objekte zum Einsatz. Zur Realisierung eines KDE Programms sind die einzelne Objekte zu erzeugen. Dabei greift der Entwickler auf eine Vielzahl von Klassen innerhalb der KDE Klassenbibliothek zurück. Alle Klassen innerhalb der Klassenhierarchie sind von der Basisklasse QObject abgeleitet und verfügen so über identische Basisfunktionalitäten. Das Verhalten der Objekte steuert der Entwickler über öffentliche Methoden. Ist ein Programm zu schreiben, sind neue Klassen anzulegen. Diese leitet man von bestehenden Klassen ab. Also kann viel bestehende Funktionalität wieder genutzt werden. Nur muss der Entwickler erstmal wissen, was die API für ihn bereithält.

@zk1:Die Widgets
@n:Widgets sind grafische Elemente der Benutzeroberfläche (User Interface). Solche Widgets miteinander kommunzieren und gegenfalls Operationen veranlassen. Dabei sind Widgets primär vom internen System abhängig. Die Interaktion mit dem System läßt sich nicht vermeiden. Auf alle Systeminteraktionen müssen die Widgets auf eine bestimmte Art reagieren. Solche System Events teilen den Widgets mit, wann ein Mausklick erfolgt ist oder wann eine Komponente den Fokus verloren hat. Hierüber weiß ein Widget dann, wann es neu positioniert oder neu aufgebaut werden muß. Jede sichtbare Komponente (Widget) ist von der Basisklasse QWidget abgeleitet. Ein Objekt vom Typ QWidget reagiert auf Ereignisse indem es virtuelle Methoden (Tabelle#2) für jedes Ereignis beim entsprechenden Widget aufruft. Da jedes Widgets anderes zu reagieren hat, ist dies in den jeweiligen Unterklassen entsprechend anders implementiert. Jedes Widget besitzt individuelle Eigenschaften. Zum Beispiel kann ein Widget einen bestimmten Zeichensatz, Stil, Farbe usw verwenden. Dies ist intern ebenfalls durch Objekte realisiert. Deshalb hält jedes Widget eine Reihe von Verweisen auf einzelne Eigenschaftsobjekte. So lassen sich Eigenschaften sehr dynamisch zuordnen. Die QWidget Klasse ist ebenfalls von der Klasse QObject abgeleitet. Aus diesem Grund können die Widgets auf die Implementierung von Signale und Slots zurückgreifen. Bei stattfindenen Benutzerinteraktionen werden sogenannte Signale an andere Interessenten herausgeschickt. Die sogenannten Slots werden verwendet, um auf diese Ereignisse/Signale reagieren zu können. Von Haus aus stellen die Widgets eine Reihe von Slot-Funktionen für alle Default Events bereit. Es gibt aber ach benutzerdefinierte Slots, welche je nach Anwendungsfall vom Entwickler zu implementieren sind. Auf diese Weise gelangen Widgets an Signale die vorerst gar nicht als wichtig erachtet wurden. Das richtige Gesamtverhalten des Objekts ist so immer gesichert.

@yu:Tabelle#2:Verschiedene Ereignismethoden
@y1:Methode Argumente
@y:Void mousePressEvent (KMouseEvent *)
Void mouseReleaseEvent (KMouseEvent *)
Void mouseDoubleClickEvent (KMouseEvent *)
Void keyPressEvent (KKeyEvent *)
Void keyReleaseEvent (KKeyEvent *)
Void focusInEvent (KFocusEvent *)
Void focusOutEvent (KFocusEvent *)

@zk1: Flexible Ereignisbehandlung
@n:Die Ereignisbehandlung ist in Toolkits und Betriebssystem eine fehlerbehaftete und fehlerträchtige Angelegenheit. Deshalb existiert innerhalb von KDE ein einfacher aber sehr leistungsfähigen Mechanismus zur Ereignisverarbeitung. Intern ist dies innerhalb der Qt Bibliothek implementiert. Nach der Objektorientierung sollte der Anwendungskode immer unabhängig aufgebaut sein, um so die verschiedensten Komponenten einsetzen zu können. Genau hier setzt Qt an, um die Kopplung zwischen Komponenten zu verhindern. So werden Signale nicht mehr an konkrete Objekte versandt, sondern an sogenannte unabhängige Slots.

Das Signal / Slot Konzept hilft dem Entwickler die Kommunikation zwischen Objekten besser zu beherrschen. Dies erlaubt es den einzelnen Objekten anonyme Signale rauszuschicken, wobei irgendwo eine Slot-Funktion eines Objekts aufgerufen wird. Das Senderobjekt hat dabei keine Ahnung, wer der Empfänger der Nachricht ist. Dies erlaubt es anwendungensunabhängige und wiederverwendbare Klassen zu realisieren. Die gesamte Logik der Anwendung steuert der Entwickler darüber, wie dieser die Signale und Slots miteinander verbindet. Hierüber wird entschieden, wie sich die Anwendung zur Laufzeit verhält. Der Signal/Slot Mechanismus ist typsicher implementiert. Sollte eine Anwendung versuchen ein Signal an einem Slot mit falschem Parametertyp zu verbinden, wird eine Error-Nachricht erzeugt und die Verbindung ignoriert. Der Signal/Slot Mechnanismus ersetzt die traditionelle Callback-Technik. Denn diese hat den Vorteil keine Laufzeitfehler mehr in Programmen zu erzeugen.

@zk1:Das Konzept besitzt eine Reihe von Vorteilen:
@n:Für jede Klasse läßt sich eine beliebige Anzahl von Signalen und Slots definieren. Die Nachrichten die verschickt werden, können über beliebige Argumentenanzahl verfügen und vom beliebigen Typ sein. Ein Signal kann mit einer Reihe von Slots verbunden werden. Die Nachricht wird somit jeden angeschlossenen Slot zugestellt. Genauso kann ein Slot mehrere Signale von verschiedenen Objekten erhalten. Eine Verbindung zwischen Signalen und Slots läßt sich dynamisch aufbauen. Sobald ein Objekt vom Typ QObject gelöscht wird, werden automatisch durch den Destruktor die bestehenden Verbindungen auch gelöscht (Signal/Slot). Alle Klassen die Signale oder Slots verwenden wollen, müssen von der Basisklasse QObject abgeleitet werden. Der typische Fall von Signalen und Slots läßt sich am besten anhand eines Beispiels skizzieren. Angenommen eine Anwendung besteht aus einem Dialog (KDialog), welcher beendet wird, sobald der Benutzer die Schaltfläche (KPushButton) "OK" drückt. Der Entwickler wird zur Umsetzung die Klassen KDialog und KPushButton hierzu nutzen. Die KPushButton Klasse verfügt standardmäßig über das Signal clicked(), welches rausgeschickt wird, sobald der Benutzer die Schältfläche betätigt. Die KDialog Klasse hat eine Default-Slot- Funktion accept(), welche den Dialog beendet und schließt. Somit ist alles da, was wir benötigen. Der Entwickler kann die benötige Funktionalität schnell erzielen, indem er das clicked() Signal des KPushButton mit der accept() Default-Slot-Funktion des KDialog Objektes verbindet. Damit man wirklich alle Objekt miteinander verbinden kann, wird in der Klasse QObject die Methode connect() für solche Zwecke bereitgestellt.

@zk1:Vereinfachungshilfe
@n:Mittlerweile gibt es auch RAD-Tools unter LINUX. Hierzu zählt »KDevelop« mit dessen Hilfe sich schnell KDE 2.2 Anwendungen realisieren läßt. Speziell Benutzeroberflächen lassen sich damit komfortabel erstellen. Den korrespondierenden Quellcode generiert KDevelop hierbei automatisch. Der Aufbau des Werkzeuges ist übersichtlich, da mittels Registerzungen alles schnell erreichbar ist (Debugger, Dokumentation, Fehlermeldungsfenster, SourceCode). Auf der Menü-Ebene läßt sich der KDE Application Wizard starten, womit sich mittels verschiedener Dialoge ein Rahmenkode einer KDE 2.2 Anwendung generieren läßt. Ebenfalls über das Menü gelangt man in der GUI-Editor. Die Einstellungen für ein aktives Projekt läßt sich über den Projektoptionsdialog voreinstellen. Sobald KDevelop aufgerufen wurde, kann ein Projekt mittels des Menüpunktes »Projekt/KAppWizard« angelegt werden. Als nächstes gibt man im Dialog an, welche Applikationsart man erzeugen will. In unserem Fall sollte eine normale KDE2 Anwendung, also der Eintrag »KDE 2 Normal« reichen. Im folgenden Dialog ist der Name des Projektes einzutragen. Dieser ist groß zu schreiben und könnte »Kde2App« heissen. Zusätzlich läßt sich hier noch der Autorenname, Versionnummer und ein Programm Icon angeben. Sobald man die Schaltfläche "Fertig" jetzt betätigt, wird das gewünschte Projekt angelegt. Natürlich wollen wir uns das Beispiel auch mal anschauen. Mittels des Menüpunktes »Erzeugen« werden die Makefiles erstellt, das Programm kompiliert und dann ausgeführt. Das Beispiel eignet sich ideal für den Einstieg in die KDE – Programmierung. Man durchschaut den Kode recht schnell. Auf der linken Fensterseite findet man alle Projekt-Dateien aufgelistet. Die einzelnen

Dateiinhalte kann man sich per Mausklick dann im rechten Fenster anschauen.

((KDev1.tiff))
@b:So sieht die KDevelop Benutzeroberfläche nach dem Aufruf aus.

((Ansicht.tiff))
@b:Die Ansicht läßt sich in KDevelop individuell einstellen.

@zk1:Einrichten
@n:Mit KDE 2.2 steht nun die KDevelop Version 2.0 ins Haus. KDE 2.2 installiert dieses Werkzeug standardmäßig mit. Sollte ihre Distribution damit noch nicht ausgestattet sein, kann man es von der Website www.kdevelop.org beziehen. Damit man es direkt auf die eigene Umgebung anpassen kann, sollte man auf die Sourcen zurückgreifen. So lassen sich leichter Patches einspielen oder das Programmverzeichnis angeben. Wir beschreiben hier, wie man die KDevelop Sourcen kompiliert und einrichtet. Wählen sie die entsprechenden fertigen Pakete für ihrer Distribution aus. Andernfalls wird es unweigerlich zu Problemen kommen. Sobald man »kdevelop-2_src.rpm« herunterladen hat, sollte man es mittels des Tools kpackage installieren. Die Sourcen sollten jetzt im Verzeichnis /usr/src vorliegen. Für die Installation und Konfiguration sollte man als Super-User arbeiten. Also meldet man sich als Root-Benutzer beim System an. Um den Quellcode nach den eigenen Vorstellungen zu kompilieren, übergibt man eine Vielzahl von Parametern dem Konfigurationskript ./configure. Zu dieser Gattung zählt der Parameter --prefix=/usr/local/kdevelop/, dessen Zweck darin besteht, das Programmverzeichnis festzulegen. Mittels »make« und »make install« schliesst der Super-User die Installation von KDevelop ab. Sollten während der Kompillierung Probleme auftauchen und eine Bibliothek nicht gefunden werden, kann es sein, daß die etc/d.so.conf entsprechend angepasst werden muß. Manchmal genügt es auch, vor jeder erneuten Kompilierung die Anweisung rm config.cache und anschließend make clean auszuführen.

((Erweit.tiff))
@b:KDevelop läßt sich auch mit weiteren Werkzeugen ausstatten.

((Env.tiff))
@b:Die Pfade zu KDE und Qt lassen sich unter den Kdevelop Einstellungen vorgeben.

@zk1:Erstes Praxisbeispiel
@n:Als Einführung erstellen wir ein kleines Programm Beispiel. Hieran soll der grundlegende Aufbau einer KDE 2 Anwendung ersichtlich werden. Zu Beginn empfiehlt es sich immer ein Grundgerüst der Anwendung zu erstellen. Dabei nutzt man die zahlreichen GUI-Komponenten der KDE 2.2 Bibliothek. Diese baut man dann Schritt für Schritt mit weiteren Funktionalitäten aus. So reduziert sich der Arbeitsaufwand entsprechend. Zu Beginn soll die Anwendung lediglich aus einem Fenster und einer Schaltfäche bestehen und auf Ereignisse reagieren können. Um Objekte im Programm zu nutzen müssen die entsprechenden Headerdateien über die Präprozessordirektive eingebunden werden. Wir binden hier »kapp.h«, »kmainwindows.h«, »qobject.h« und »qpushbutton.h« ein, da wir diese Klassen nutzen wollen. Solche Headers liefern dem Entwickler die Information, wie die öffentliche Schnittstelle der Klasse aussieht. Wie üblich in C++ Programmen wird die Programmausführung über die Funktion main() gestartet. Zuerst ist bei jeder KDE Anwendung ein lokales Objekt vom Typ KApplication zu erzeugen (myapp). Dabei werden die Parameterangaben in der Kommandozeile dem Programm übergeben und die KDE Umgebung entsprechend initialisiert. Jetzt ist aber noch nichts zu sehen. Dafür ist ein sogenanntes TopWidget zu erzeugen. Mittels des Schlüsselworts new() instanziieren wir ein TopWidget-Objekt vom Typ KMainWindow. Dieses repräsentiert das Hauptfenster der Anwendung. Allerdings ist das Fenster noch nicht sichtbar. Dazu muß die Methode show() der Klasse QWidget aufgerufen werden. Damit das Programm einen Zugriff auf das Objekt erhält, wird dessen Adresse innerhalb einer Zeigervariable (mywindow) gespeichert. Jeglicher Zugriff im Programm erfolgt nun über diese Zeigervariable (pointer). Dem Hauptfenster kommt die Aufgabe zu die einzelnen Oberflächenelemente (Widgets) zu verwalten. Im Folgenden legen wir eine Schaltfläche innerhalb des Hauptfensters an. Also erzeugen wir ein Objekt vom Typ KPushButton mittels des Schlüsselworts new(). Bei der Erzeugung ist die Button-Beschriftung anzugeben und innerhalb welcher Oberflächenkomponente (mywindow) die Schaltfläche dargestellt werden soll. Innerhalb einer Zeigervariable (mybutton) sichert man die Adresse des Objekts ab. Die Größe der Schaltfläche (mybutton) und dessen Position innerhalb des Fensters läßt sich über die Methode setGeometry(x1,y1,x2,y2) setzen. Die ersten 2 Angaben beziehen sich auf die Größe. Die letzten 2 Angaben auf die Ausrichtung der Komponente. Natürlich soll die Schaltfläche im Fenster selbst erscheinen. Hierzu ist die Methode show() der Klasse QWidget aufzurufen. Über diese Schaltfläche wird letztlich die Anwendung beendet. Anschließend wird mittels der Methode setMainWidget() das Hauptfenster (mywindow) der Anwendung (myapp) zugeteilt. So werden ab sofort alle Ereignisse der Applikation automatisch an das Hauptfenster weitergeleitet. Jetzt muß die Anwendung noch auf Ereignisse reagieren können. Hier existiert das mächtige Signal/Slot–Konzept. Damit eine Schaltfläche auf ein Ereignis reagieren kann, ist die Schaltfläche (mybutton) mit einer konkreten SLOT Funktion zu verbinden. Da jede Applikation irgendwann mal beendet wird, hat die Klasse KApplication solch eine Default-Slot-Funktion (quit) standardmäßig schon implementiert. Somit brauchen wir nur das Ereignis clicked() der Schaltfläche (mybutton) mit der Default-Slot-Funktion quit() von KApplication zu verbinden. Über die Methode connect() der Klasse QObject erledigen wir das. Allerdings kann die KDE Anwendung immer noch auf keine Ereignisse reagieren. Diese Aufgabe übernimmt dieMethode exec() des Objekts KApplication wahr. Bei dieser Methode handelt es sich um eine Schleife, welche ständig abruft, ob ein Ereignis vom X-Server ausgelöst worden ist. Sollte dies der Fall sein, interpretiert KApplikation das Ereignis und leitet es an die betroffenen Objekte (Widgets) weiter. Die Schleife wird erst beendet, wenn die Slot-Funktion quit() des

QApplication Objektes aufgerufen wird. Das Folgende Kodefragment legt ein einfache KDE 2.2 Anwendung an und zeigt ein Fenster mit einer Schaltfläche an. Dies sieht im Detail so aus:
((Wizard.tiff))
@b:KDevelop stellt auch einen Wizard zur Verfügung, worüber sich Anwendungen erzeugen lassen.

@l:Code–Beispiel#1:
#include <\<>kapp.h>
#include <\<>kmainwindow.h>
#include <\<>kpushbutton.h>
#include <\<>qobject.h>
int main( int argc, char *argv[]) {
// Das Applikationsobjekt erzeugen
KApplication myapp( argc, argv, "app" );
// Das Hauptfenster erzeugen
KMainWindow *mywindow = new KMainWindow();
mywindow.resize ( 250, 250 );
// Die Schaltfläche anlegen
KPushButton *mybutton = new KPushButton("Beenden!", mywindow);
mybutton.setGeometry(10,10,50,50);
mybutton.show();
// Die Schaltfläche an eine SLOT-Funktion anbinden
QObject::connect(mybutton,SIGNAL(clicked()), &myapp, SLOT(quit()));
// Das Hauptfenster der Anwendung zuordnen
myapp.setMainWidget( &mywindow );
// Die Anwendung starten
return myapp.exec();
}

((Kode.tiff))
@b:Hier sehen Sie den Code unseres ersten Beispiels in eMacs dargestellt.

((app1.tiff))
@b:KDevelop kann wertvolle bei der Entwicklung leisten. Hier sehen Sie ein fertig entworfenes Fenster.

@zk1:Interner Aufbau
@n:Der konzeptioneller Aufbau einer KDE Anwendung sieht überall ähnlich aus. Die Klasse KApplication hat die Aufgabe alle grundlegenden Applikationsdienste bereitzustellen. Intern wird hierüber die KDE Umgebung initialisiert. Dann wird die Klasse KMainWindow genutzt, um das Hauptprogrammfenster der Anwendung zu erzeugen. Das Fenster wird dann mit einzelnen Oberflächen-Komponenten (KListBox, KComboBox, KPushButton) ausgestattet. Natürlich übernimmt die Klasse KMainWindow die Erzeugung und Positionierung der einzelnen Komponenten. Jegliche Interaktion der Widgets passiert über die Klasse KAapplication. Die eigentlichen Nachrichten erhält die Klasse KApplication vom X-Window-System zugestellt. Das Objekt vom Typ KApplication hat die Aufgabe alle Nachrichten an die entsprechenden Widgets weiterzuleiten. So kann ein Widget dann letztlich auf Ereignisse reagieren.

((Prog.tiff))
@b:Hier wurde unser kleines Beispiel über die Kommandozeile aufgerufen.

((Dateien.tiff))
@b:Die Ansicht zeigt alle Dateien des aktuellen Projektes an.

@zk1:Zweites Praxisbeispiel
@n:Nun erweitern wir das Ganze noch etwas , damit wir auch eine richtige KDE2-Anwendung erhalten. Die typischen Elemente einer KDE 2-Anwendung sind Fensterleiste, Menüleiste, Werkzeugleiste und Statusleiste. Erst dann kann man heute von bedienungsfreundlich sprechen. Wie man sowas implementiert, schildern wir jetzt der Reihe nach. Im Folgenden implementieren wir die Klasse (Kde2app). Unsere Klasse "Kde2app" greift auf verschiedene Klassen der KDE Library zurück. Also sind die entsprechenden Headers (kapp.h, ktmainwindow.h, kstatusbar.h, kmenubar.h, kpopupmenu.h, ktoolbar.h) einzubinden. Jede Klasse muß über einen Konstruktor verfügen. Unser Konstruktor ist von der Klasse KMainWindow abgeleitet und erzeugt so automatisch das Hauptfenster für die Anwendung. Innerhalb des Konstruktors werden die verschiedenen Widgets erzeugt und entsprechend konfiguriert. Da innerhalb der KDE-Klassenhierarchie eine gewisse Polymorphie herrscht, sind diese Klassen ähnlich zu handhaben. Der Konstruktor sieht Folgermaßen aus:

@l:Code–Beispiel#2:
#include <\<>kapp.h>
#include <\<>kstdaccel.h>
#include <\<>kiconloader.h>
#include <\<>kmenubar.h>
#include <\<>kaction.h>
Kde2app::Kde2app (const char *name) : KTMainWindow(name) { // Konstruktor }

@zk1:Das neue Konzept
@n:Bei allen bisher verfügbaren Toolskits war enorm viel Handarbeit bei der Programmierung nötig. Daraus hat man wohl bei KDE gelernt. Zahlreiche Standardaufgaben wurden in KDE 2.2 automatisiert. Bisher musste man die Objekte einer Oberfläche immer explizit erzeugen. Steht der Rohbau (KApplication, KMainWindow) erst einmal, werden alle weiteren Widgets automatisiert erzeugt. Ebenso war anzugeben, mit welchen Objekten ein Objekt kommunizieren will und ob die Komponente auf der Oberfläche angezeigt werden soll. Darüber hinaus mußte sich ein Objekt einem zentralen Ereignisverteilungsobjekt anmelden, wenn es über bestimmte Ereignisse informiert werden möchte. Dies führt KDE 2.2 quasi im Hintergrund für einen durch. In diesen Genuss kommt man allerdings nur, wenn man einen Standardweg einhält. Dies dürfte aber kein großes Problem sein, da übliche Desktop-Anwendungen ja eh standardisiert aufgebaut sind und sich an bestimmte Entwurfsregeln halten müssen. Jede Anwendung verfügt heute über eine Menüleiste mit den einzelnen Menüs. Alle Programmfunktionen werden innerhalb von Menüeinträgen dem Anwender bereitgestellt. Ebenso wird über die Werkzeugleiste alle Programmfunktionen mittels Icons verfügbar gemacht. Zum Schluß kommt noch die Statusleiste, wo alle Programmausgaben angezeigt werden. Es wäre unsinnig dies immer wieder neu zu kodieren. Also hat man in KDE 2.2 den Einsatz dieser Komponenten erheblich vereinfacht. Da jegliche Komponente auf Ereignisse reagieren muß, werden sogenannte Aktionsobjekte zuerst angelegt. Erst danach werden die einzelnen Oberflächenelemente angelegt. Jedoch verbindet man diese sofort mit den entsprechenden Aktionsobjekt. Die Verwendung der Widgets wird dadurch um einiges einfacher. Einige Sachen werden standardmäßig vorausgesetzt und deren Aktion im Hintergrund ausgeführt, ohne das der Entwickler davon etwas mitbekommt. Das neue Konzept in KDE 2.2 erlaubt es verschiedene Programmfunktionen zusammenzufassen und diese zu beschreiben und zu aktivieren. Um jedoch so vorgehen zu können, muß man sich überlegen, welche Ereignisse innerhalb der eigenen Anwendung auftreten.

@zk1: Der Anwendungsaufbau
@n:Unsere Anwendung soll lediglich aus einer Menüleiste mit einem einzelnen Menü bestehen. Dieses Menü soll zwei Menüeinträge aufnehmen. Diese Programmfunktionen sollen innerhalb einer Werkzeugleiste mittels zweier Iconsymbol repäsentiert werden. Zum Schluß soll mittels einer Statusleiste die verschiedenen Programmeldungen anzeigbar sein. Der Aufbau lässt ersehen, über welche Aktionen die Anwendung verfügt.

((ProjOpt.tiff))
@b:Die allgemeinen Projekt Informationen lassen sich in KDevelop auch einstellen.

@zk1: Die Realisierung
@n:Also legen wir zu Beginn die einzelnen Aktionsobjekte an. Über die Klasse KAction läßt sich nicht nur eine Aktion spezifizieren, sondern gleichzeitig wird das Oberflächenelement darüber auch grundlegend konfiguriert. In unserer Anwendung können zwei Aktionen von den zwei Menüeinträgen (load,quit) ausgelöst werden. Alle anderen Aktionen sind ableitbar. Also sind zwei Aktionsobjekte zu Beginn anzulegen. Über Aktionen läßt sich angeben über welche Beschriftung die Komponente verfügt und über welches Tastaturkürzel dieses aufgerufen werden kann. Ebenso läßt sich die Slot-Funktion angeben, welche beim Eintritt der Aktion bei irgendeinem Objekt aufgerufen wird. Der Kode sieht Folgendermaßen aus:

@l:KAction *load = new Kaction
("Laden",QIconSet(BarIcon("pic1")),CTRL+KEY_L,this,SLOT(slotLoad()),this);
KAction *quit = new Kaction
("Beenden",KstdAccel::quit(),kapp,SLOT(closeAllWindows()),this);
@n:Danach werden die einzelnen Oberflächenelemente erzeugt und direkt mit einem
Aktionsobjekt verbunden. Zuerst ist das Menü (mymenu) anzulegen, bevor man die Menüleiste erzeugen kann. Mittels des Schlüsselworts new() wird das Objekt vom Typ QPopupMenu instanziiert. Der Kode dazu sieht Folgendermaßen aus.

@l:QPopupMenu *mymenu = new QPopupMenu;
@n:Jedes Menü verfügt üblicherweise einzelne über Menüeinträge. Diese haben wir ja schon als KAction Objekte (load,quit) realisiert. Also verbinden wir das Widget (mymenu) mit den entsprechenden Aktionsobjekten (load,quit). Hierüber wird festgelegt, welche Aktionen vom Widget ausgehen können. Dies geschieht mittels der Methode plug() aus der Klasse KAction. Dies sieht so aus:

@l:load->plug(mymenu);
quit->plug(mymenu);

@n:Nun ist nur noch die Menüleiste zu erzeugen. Beim Aufruf der Methode menuBar() aus der Klasse KMainWindow wird automatisch ein Objekt vom Typ KMenuBar instanziiert. Mittels der Methode insertItem() geben wir die Menü-Beschriftung sowie das entsprechende Menüobjekt (mymenu) an. @l:MenuBar()->insertItem("Datei",mymenu);
@n:Hiermit haben wir schon ein funktionierendes Menü umgesetzt. Dies war bisher um einiges
schwerer zu realisieren.

@zk1: Werkzeugleiste
@n:Damit unsere Anwendung wirklich benutzerfreundlich ist, legen wir noch eine Werkzeugleiste an. Da alle Programmfunktionen dem Programm bereits bekannt sind, braucht die Werkzeugleiste (KToolBar) nicht näher konfiguriert werden. Bei der Erzeugung wird automatisch entsprechend alles eingerichtet. Sobald man die Methode toolBar() aus der Klasse KMainWindow aufruft, wird ein Objekt vom Typ KToolBar instanziiert. Mittels der Methode plug() verbindet man das Widget mit seinem entsprechenden KAction Objekt. Das Widget reagiert dann so, wie es im KAction Objekt angegeben ist. Der Kode sieht so aus:

@l:Load->plug(toolBar());
@n:Um die Icons der Werkzeugleiste zu laden, wird intern auf die Klasse KIconLoader zurückgegriffen. Über diese Klasse werden alle Icons verwaltet. Welche Icons wir nutzen wollen, haben wir im Aktionsobjekt bereits spezifiziert.

@zk1: Statusleiste
@n:Natürlich sollte eine Anwendung heute über eine Statusleiste verfügen. Sobald man die Methode statusBar() aus der Klasse KMainWindow aufruft, wird eine Instanz der vom Typ KStatusBar erzeugt. Über die öffentliche Methode message() wird angegeben, was innerhalb der Statusleiste angezeigt werden soll. Im Detail sieht das so aus:

@l:StatusBar()->message("Fertig!");
@zk1: Die Slot-Funktion
@n:Damit die Programmfunktionen auch für den Anwender bereitstehen, muß noch die Slot-Funktion implementiert werden. Um eine Datei zu öffnen, legen wir die Slot-Funktion slotLoad() an. Diese bedient sich der standardisierten Klasse QFileDialog, um einen gewöhnlichen DateiÖffnen Dialog darzustellen. Mittels der Methode getOpenFileName() wird ermittelt, welcher Dateiname vom Anwender ausgewählt wurde. Anschließend kann eine beliebige Operation darauf erfolgen. Diese ist noch nicht implementiert. Folgendermaßen sieht die Slot-Funktion aus:

@l:Kd2app:slotLoad() {
Kstring fileName = KfileDialog::getOpenFileName(0,0,this);
If (!fileName.isEmpty())
{ // nicht implementiert! }
else
{ // nicht implementiert! }
}

@zk1:Die Hauptprogrammfunktion
@n:Zum Schluß ist natürlich noch die Hauptprogrammfunktion (main) für unserer neue Klasse Kde2app anzulegen. Hier wird wieder das Objekt vom Typ KApplication wieder erzeugt und die Kommandozeilenparameter dem Programm übergeben. Anschließend wird unsere neue Klasse "Kde2app" erzeugt und dessen Adresse in einer Zeigervariable gesichert. Unsere neue Klasse wird als Haupt-Widget innerhalb der Anwendung bestimmt. Zum Schluß wird das Fenster angezeigt und die Anwendung gestartet. Im Detail sieht das Ganze so aus:

@l:int main ( int argc, char **argv ) {
Kapplication kapp (argc, argv );
Kde2app prog;
kapp.setMainWidget ( &prog );
prog.show();
return kapp.exec();
}

((app2.tiff))
@b:Hier sehen Sie das Ergebnis innerhalb von KDevelop. Hier wird unsere Beispiel Anwendung mit ihren diversen Funktionalitäten angezeigt.

@zk1:Fehlerfalle
@n:Bei der Programmerzeugung oder Kompilierung können natürlich Fehler auftreten.  Meistens sind die Pfade dann nur falsch gesetzt. Am häufigsten werden die KDE oder Qt Bibliothek nicht gefunden. Ebenso kann der Pfad zu den includes-Files (KDE oder Qt) nicht richtig gesetzt sein. Deshalb sollte man in Kdevelop überprüfen, ob dort die Pfadangaben korrekt sind. Die Libraries sollten im Pfad /usr/lib stehen, während die Includes-Files unter /usr/include zu finden sein dürften. Sollte dies nicht sein, muß man es entsprechend anpassen. Ebenso kann es vorkommen, daß die KDE Namenskonventionen nicht eingehalten wurden und dies zum Fehler führte. Standardmäßig fängt eine Klasse mit einem Großbuchstaben an. Die Methoden werden hingegen immer klein geschrieben. Dies ist bei der Entwicklung zu beachten!

@zk1:Hilfestellung
@n:Während der Entwicklung ist es typisch das man gerade eine Information über eine bestimmte Klasse sucht. Deshalb stellt das Entwicklungswerkzeug »Kdevelop« das Hilfemenü »KDE Library Referenz Dokumenation« zum Nachschlagen bereit. Wird dieses aufgerufen, wird der Dokumentationsbrowser geöffnet und zeigt die Startseite der KDE-Referenz an. Hier findet man schnell die gerade benötigten Klassen und Funktionen. Einen schnellen Zugriff auf eine bestimmte Klasse erhält man über die alphabetische Klassenliste. Zu jeder Klasse werden die verfügbaren Konstruktoren und Methoden aufgelistet. Wenn man einen Eintrag anklickt, erhält man weiterführende Informationen, wie man diese einsetzen kann. Dies kann in der Praxis mehr als nützlich sein, wenn man einfach seinen Fehler nicht findet und dringend ein entsprechendes Beispiel dazu sucht.

((api1.tiff))
@b:Der Dokumentationsbrowser gibt Auskunft über die öffentlichen Methoden einer Klasse. Hier werden die Details der Klasse KMainWindow dargestellt.

((api2.tiff))
@b:Im Dokumentationsbrowser alle verfügbaren Methoden einer Klasse auflisten lassen. Der Entwickler kann so fündig werden.

@zk1:Schluß
@n:Für den Einstieg in die KDE Programmierung bietet die Webseite http://developer.kde.org einige Tuturials an. Dort findet man etliche Beispiele zur Veranschaulichung. Da die Quellen offen liegen , kann jeder diese beliebig erweitern. Sobald man einige Beispiele nachvollzogen hat, werden die Konzepte um so klarer. Mittels des RAD-Tool »KDevelop« kann man sich das Ganze noch erleichtern. Die neue Version enthält jetzt eine noch umfangreichere Dokumentation. Aber ums studieren, kommt man weiterhin nicht herum.