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