Bisher haben Sie neben der Sprache C++ auch eine Reihe von Werkzeugen kennen gelernt, mit denen Sie eigentlich alle Entwicklungsaufgaben erledigen könnten. Das ist jedoch zuweilen etwas mühsam; während Freaks auf ihre Kommandozeilentools schwören, mutet Ihnen die Arbeitsweise vielleicht ein wenig archaisch an. Wesentlich bequemer und damit auch produktiver wird die Programmierung mit integrierten Entwicklungsumgebungen, Integrated Development Environments oder kurz IDEs. Wenn Sie schon Programme unter Windows oder auf dem Mac geschrieben haben, kennen Sie sicher Umgebungen wie Microsoft Visual Studio, Borland Delphi oder Metrowerks CodeWarrior.
Diese verfügen alle über folgende Merkmale:
Ich will Ihnen in diesem Kapitel vor allem zwei IDEs vorstellen, die alle diese Kriterien erfüllen (und noch einige mehr):
Doch zunächst will ich Ihnen zeigen, dass auch der bereits vorgestellte XEmacs zu einer fast vollwertigen IDE werden kann.
Schon als wir ab Seite 617 den XEmacs näher betrachteten, habe ich Sie darauf aufmerksam gemacht, dass er eigentlich viel mehr als nur ein Editor ist. Es gibt für ihn so viele Erweiterungen, dass Sie nichts anderes mehr benötigen. Natürlich gilt das auch im Hinblick auf die Programmierung. Wir wollen uns nun die wichtigsten Funktionen ansehen, die Sie bei der Verwendung des XEmacs als IDE brauchen werden.
Obwohl ich hier nur vom XEmacs rede, funktionieren die meisten der vorgestellten Merkmale auch beim GNU Emacs.
Dass der Editor Syntaxeinfärbung, Markierung von Klammern und automatisches Einrücken beherrscht, habe ich Ihnen schon auf Seite 637 gezeigt. Anhand der Dateiendung (.cc, .C, .cpp, .cxx, .hh oder .hxx) erkennt er automatisch, dass es sich dabei um einen C++-Quelltext handelt, und passt seinen Modus entsprechend an. Auch die Navigationsmöglichkeiten ergeben sich daraus.
Liegt die Dokumentation zu einer Funktion im Unix-man-Format vor, so können Sie diese direkt im XEmacs aufrufen. Das ist zum Beispiel für die C-Standardbibliothek und einige sonstige Bibliotheken der Fall.
Angenommen, Sie möchten die Bedeutung der Parameter der Funktion
strstr() wissen. Dann klicken Sie doppelt darauf, um sie zu markieren.
Dann wählen Sie aus dem Menü HELP — MISC — UNIX MANUAL und
erhalten in der Echo-Zeile, also der untersten Zeile des Fensters, die
Meldung:
Hier müssen Sie nur noch die Eingabetaste drücken und schon haben Sie die gewünschte Information vor sich.
Wenn Sie mit dem XEmacs Programme entwickeln, ist es am sinnvollsten, mit Makefiles zu arbeiten. Natürlich können Sie auch hier die Quelldateien einzeln übersetzen und linken lassen, aber das ist genauso mühselig wie über die Kommandozeile. Gehen wir also davon aus, Sie hätten bereits ein Makefile (diese lassen sich ja auch sehr komfortabel mit XEmacs erstellen und bearbeiten).
Um den Compiler zu starten, gibt es wieder viele Wege: die
Schaltfläche COMPILE, der Menüpunkt TOOLS — COMPILE oder ganz
klassisch über die Tastatur: Alt+X und dann "compile" eingeben. Dann
werden Sie noch gefragt, wie Sie make aufrufen wollen. Die Vorgabe
enthält die Option -k, die dafür sorgt, dass der Übersetzungsvorgang
nicht bei einer fehlerhaften Datei abgebrochen wird, sondern dass
andere Dateien, die von dieser unabhängig sind, auch noch kompiliert
werden.
Treten bei der Übersetzung Fehler auf, so werden die entsprechenden Meldungen im unteren Teil des Fensters angezeigt. Mit einem Klick darauf gelangen Sie sofort an die angegebene Stelle im Quelltext und können nach der Ursache suchen. Im Programm in Abbildung 7.1 fehlt einfach das Semikolon nach der Anweisung innerhalb der Schleife.
Ebenso leicht ist es, das erfolgreich erzeugte Programm aus dem XEmacs
zu starten. Da es ja auch einem Shell-Kommando entspricht, müssen Sie
nur noch darauf achten, den richtigen Pfad zu verwenden. Als lokales
Verzeichnis sieht der XEmacs immer das Verzeichnis an, aus dem er
gestartet wurde. Liegt Ihr Programm nicht dort, müssen Sie einen relativen
oder absoluten Pfad mit angeben. Rufen Sie also TOOLS — SHELL
COMMAND oder Alt+! auf und geben Sie den Namen Ihres Programms und
gegebenenfalls weitere Argumente ein. Wie Sie wissen, müssen Sie das
nur das erste Mal tun; der XEmacs merkt sich solche Eingaben
und lässt Sie mittels der Tasten
und
auf frühere zugreifen. Die
Ausgaben Ihres Programms erscheinen dann in einem Fenster des
XEmacs.
Wenn Sie Ihr Programm debuggen wollen, gehen Sie ähnlich vor. Standardmäßig ist der XEmacs mit dem gdb integriert, also dem textorientierten Debugger, den Sie von Seite 685 kennen. Wenn Sie nun TOOLS — DEBUG (GDB) wählen, werden Sie noch nach dem Namen der ausführbaren Datei gefragt und los geht’s. Nun ändert sich auch die Leiste der Schaltflächen und es erscheinen solche, die für das Debuggen gebraucht werden (Abbildung 7.2); wenn Sie den Mauszeiger über eine davon bewegen, können Sie deren Bedeutung in der Echo-Zeile lesen.
Nun können Sie entweder über die Schaltflächen oder direkt an der Eingabeaufforderung des gdb alle bekannten Befehle aufrufen und auf diese Weise Schritt für Schritt die Fehler in Ihrem Programm suchen.
Auch die Funktionen zur Versionskontrolle sind direkt in den XEmacs integriert. Unter Linux wird dabei standardmäßig RCS verwendet. Aber auch CVS (siehe Seite 707) und andere werden unterstützt. Die entsprechenden Funktionen sind hinter dem Menüpunkt TOOLS — VC, teilweise auch unter TOOLS — PCL CVS verborgen - aber natürlich gibt es für alles auch wieder Tastenkürzel. Wenn Sie sie nicht standardmäßig aktiviert haben, müssen Sie die Unterstützung für die Versionsverwaltung vor dem ersten Aufruf mit TOOLS — VC — LOAD VC laden.
Jede Versionsverwaltung legt eine Reihe von Dateien zur eigenen Buchhaltung an. XEmacs orientiert sich an diesen und versucht, das System, das jeweils für die aktuelle Datei passt, auch zu unterstützen. Gibt es also beispielsweise ein Unterverzeichnis RCS, so werden die RCS-Funktionen aktiviert und so weiter. Die Aktionen, die XEmacs unter TOOLS — VC bietet, beziehen sich vorwiegend auf die Datei im aktuellen Puffer.
Die wichtigsten Funktionen für RCS sind:
Interessant ist es auch, die aktuell bearbeitete Version einer Datei mit der archivierten zu vergleichen. Dazu bietet sich Ediff an, zu dem wir gleich kommen.
Die wichtigsten Funktionen für CVS sind:
Darüber hinaus gibt es noch ein paar weitere Funktionen, deren Bedeutungen aber aus den Menüpunkten schnell einsichtig werden.
Ein sehr hilfreiches Werkzeug zum Vergleich von Dateien, Verzeichnissen und anderem ist Ediff. Sie erreichen es über das Menü TOOLS — COMPARE des XEmacs. Wenn Sie das Untermenü öffnen, sehen Sie bereits die Möglichkeiten, die Ihnen Ediff bietet. Wir wollen hier zwei Dateien miteinander vergleichen, genauer zwei Versionen einer Datei.
Dazu rufen Sie TOOLS — COMPARE — FILE WITH REVISION auf. Um die Fragen, die XEmacs stellt, müssen Sie sich nicht weiter kümmern; Sie möchten ja ohnehin nur den Standardfall bearbeiten, nämlich den aktuellen Puffer mit seiner letzten archivierten Version vergleichen.
Anschließend öffnet sich ein kleines zusätzliches Steuerfenster, über das Sie Ihre Ediff-Befehle geben können. Dabei müssen Sie beachten, dass die Ediff-Tastenkombinationen nur dann funktionieren, wenn das Steuerfenster das aktive ist. Gerade wenn Sie Ihre Oberfläche so eingestellt haben, dass die Aktivierung der Fenster schon bei der Positionierung des Mauszeigers darüber erfolgen soll, kann es immer wieder zu Problemen kommen, die Ediff mit einem Piepser quittiert.
Das Arbeitsfenster des XEmacs teilt sich nun in zwei Bereiche auf, die die beiden miteinander zu vergleichenden Dateien (hier Versionen) enthalten (Abbildung 7.3). Aus der jeweiligen Statuszeile erfahren Sie, um welche Datei es sich dabei jeweils handelt.
Mit Hilfe von Ediff navigieren Sie nun durch die sich unterscheidenden Bereiche der Dateien. Diese sind jeweils andersfarbig hervorgehoben. Abweichende Zeilen werden als Ganzes markiert; einzelne Abweichungen darin werden mit einer weiteren Farbe hervorgehoben. In Prosa klingt das alles sehr kompliziert, wird aber beim konkreten Einsatz schnell einsichtig.
|
|
Auch während des Vergleiches können Sie beide Fenster noch editieren (sofern nicht eines davon schreibgeschützt ist). Die meisten Aktionen geben Sie aber durch einfache Tasten über das Ediff-Fenster an. Die wichtigsten davon sind:
+ v können Sie in beiden Puffern gleichzeitig abwärts
beziehungsweise aufwärts blättern.
+ 1 (entspricht dem !).
Sie haben gesehen, dass der XEmacs sich durchaus gut für die Programmierung eignet. Viele der bekannten Open-Source-Programmpakete wurden mit ihm geschrieben. Er enthält einen komfortablen Editor mit Syntaxeinfärbung und Einrückung, erlaubt das Starten des Compilers und das Springen zu Fehlerstellen, integriert den Debugger und die Versionsverwaltung und bietet mit Ediff ein äußerst praktisches Werkzeug zum Vergleich von Dateien und Versionen.
Von den Kriterien für IDEs, die wir am Anfang des Kapitels aufgestellt haben, erfüllt er die Punkte 3 und 6 nicht. Gerade die Verwaltung größerer Projekte mit mehreren Abhängigkeiten wird daher schwierig. Für Umsteiger aus der Windows-Welt sind vielleicht gerade diese Aspekte entscheidend, da sie den Umgang mit Make-Dateien nicht gewohnt sind. Aber auch diese Funktionen wird der XEmacs früher oder später beherrschen.
Auch das KDE-Projekt hat mit KDevelop eine eigene integrierte Entwicklungsumgebung hervorgebracht. Wie alles in KDE steht auch diese unter GPL und ist frei im Quelltext verfügbar. Die aktuellste Version erhalten Sie stets von www.kdevelop.org.
Das Programm erfüllt alle Kriterien vom Anfang dieses Kapitels, bringt einen komfortablen Editor mit, startet den Compiler (standardmäßig natürlich den GCC) direkt aus der IDE, lässt die Optionen für Kompilieren, Linken und make über Dialoge einstellen, springt aus der Fehlerausgabe direkt durch Doppelklick an die entsprechende Programmstelle, bindet einen Debugger ein, verwaltet automatisch die Makefiles und hat die Versionsverwaltung integriert.
Aber KDevelop geht noch sehr viel weiter, als "nur" diese Kriterien zu erfüllen. Die Erzeugung der Make-Dateien macht beispielsweise intensiv von autoconf Gebrauch, um die Generierung automatisch an die lokale Hard- und Softwareumgebung anzupassen. Außerdem ist mit KBabel ein zusätzliches Werkzeug direkt angebunden, um die Applikationen von Anfang an mehrsprachig zu entwickeln.
Und im Gegensatz zu den meisten anderen hier vorgestellten IDEs unterstützt KDevelop auch die Entwicklung von grafischen Benutzeroberflächen. Dazu nutzt es die in KDE verwendeten Prinzipien der Programmierung von grafischen Anwendungen auf der Basis der Klassenbibliothek Qt. Für die Gestaltung von Dialogen und fensterbasierten Applikationen bringt KDevelop kein eigenes Werkzeug mit, sondern setzt den Qt Designer ein, der vom Qt-Hersteller Trolltech stammt. Die dort erzeugten Dateien kann KDevelop in seine Projekte einbinden, daraus die nötigen Klassen generieren und übersetzen. Für andere Aufgaben gibt es wieder andere externe Werkzeuge, etwa KIconEdit für die Gestaltung von Icons.
Generell gilt auch auch bei KDevelop, was wir noch bei anderen IDEs feststellen werden und was im Gegensatz zu den unter Windows üblichen Gepflogenheiten steht: Die IDE ist in weiten Teilen nur ein Frontend, ein grafisch bedienbarer Zugriffsweg auf die darunter liegenden Werkzeuge. Compiler, Debugger etc. sind nicht im "Lieferumfang" enthalten, sondern als externe Tools vorausgesetzt und eingebunden. Auf diese Weise erreicht die IDE aber auch ein hohes Maß an Flexibilität und die Entwicklung kann sich auf die eigene Funktionalität konzentrieren.
Welche Gestaltung Sie wählen, bleibt Ihren persönlichen Vorlieben überlassen. Über EINSTELLUNGEN — KDEVELOP EINRICHTEN — BENUTZEROBERFLÄCHE können Sie auch zur Laufzeit zwischen den verschiedenen Modi umschalten.
In jedem Fall befindet sich am oberen Rand des Fensters das Hauptmenü sowie die Werkzeugleisten. Diese lassen sich über ihr Kontexmenü anpassen, verschieben oder gar ausblenden. Die zweite Leiste ist die so genannte Browserleiste, mit deren Hilfe Sie in der Dokumentation navigieren oder schnell zur Definition von bestimmten Klassen beziehungsweise Methoden springen können.
Der Editor hält sich an alle Konventionen, die Sie aus anderen Programmen für KDE kennen. So können Sie mit Strg+X ausschneiden, mit Strg+Z die letzte Aktion rückgängig machen, mit Strg+S speichern und so fort. Die Syntaxeinfärbung ist übersichtlich, ein automatisches Einrücken ist ebenso möglich wie das automatische Einfügen von schließenden Klammern beim Tippen oder das vertikale Selektieren (zu aktivieren unter BEARBEITEN — BLOCKAUSWAHL-MODUS). Zudem können Sie auch bei KDevelop Lesezeichen in den Quelltexten setzen, zu denen Sie dann später springen können.
Und noch eine nette Funktion bei KDevelop: Wenn Sie eine Datei geändert haben, die Änderungen aber noch nicht gespeichert sind, so ändert sich deren Symbol in der Karteireiter-Leiste der verschiedenen in Bearbeitung befindlichen Dateien vom KDevelop-Logo zu einer Diskette. Auf diese Weise erkennen Sie auf einen Blick, welche Ihrer geöffneten Dateien noch gespeichert werden müssen.
Apropos suchen: Natürlich können Sie auch in Ihrem Editor nach einem Begriff suchen. KDevelop hat zusätzlich das kleine Werkzeug grep eingebunden, mit dem Sie in verschiedenen Dateien gleichzeitig suchen können. Markieren Sie einfach den gewünschten Ausdruck und wählen Sie GREP aus dem Kontextmenü.
Im selben Kontextmenü darunter gibt es noch zwei andere praktische Funktionen: SUCHE IN DOKUMENTATION und GEHE ZU MANPAGE. Die erste sucht nach dem markierten Begriff in der eingerichteten Dokumentation (mittels der durch htDig eingerichteten Volltextsuche), die zweite versucht, eine mögliche zugehörige man-Seite zu öffnen.
KDevelop orientiert sich immer mehr an den "großen" IDEs unter
Windows wie Microsoft Visual Studio oder Borland C++Builder und
versucht, deren Funktionsmerkmale zum Teil nachzubilden. Dazu gehört
heutzutage auch die Codevervollständigung von Klassenelementen,
Funktionsargumenten etc. Nehmen wir an, Sie haben ein Objekt einer
bestimmten Klasse definiert und tippen dieses in Ihrem Quelltext wieder
ein, um eine Methode davon aufzurufen. Dazu setzen Sie hinter den
Objektnamen einen . oder einen -¿ (je nachdem, ob Referenz oder Zeiger).
Schon klappt unterhalb der Eingabezeile ein kleines Fenster auf, das Ihnen
die vorhandenen Methoden dieser Klasse auflistet (siehe Abbildung 7.5) -
allerdings nur die der Klasse selbst, nicht die einer Basisklasse. Wenn Sie
nun die öffnende Klammer für die Parameter eingeben, erhalten Sie ein
weiteres Hilfefensterchen, das angibt, welche Parameter diese Methode
erwartet.
|
|
Auf der ersten Seite legen Sie fest, von welchem Typ Ihr Projekt sein soll. Dabei unterstützt KDevelop mittlerweile eine (fast unübersichtliche) Vielfalt von Anwendungstypen. Diese sind auf oberer Ebene nach Programmiersprachen unterteilt - Ada, C/C++, Fortran, Java, Pascal, PHP usw. Wir wollen hier nur die wichtigsten Projekttypen auf C++-Basis betrachten.
Außerdem können Sie auf dieser Seite des Assistenten gleich das Projektverzeichnis, die Versionsnummer, Ihren Namen als Autor und sogar die Lizenz festlegen, unter der Sie die Anwendung später veröffentlichen wollen. Hier geht KDevelop natürlich von einer Open Source-Lizenz aus (siehe Seite 39) und bietet GPL, BSD, QPL und LGPL an. Diese Einstellungen wirken sich beispielsweise auf die Vorlage für .h- und .cpp-Dateien aus, in die entsprechende Kommentare dann gleich eingefügt werden. Diese können Sie aber auf den folgenden Seiten des Assistenten noch bearbeiten.
Auf der nächsten Seite legen Sie aber zunächst erst fest, mit welchem Versionsverwaltungssystem Sie Ihr Projekt bearbeiten wollen. Von Haus aus werden CVS und Subversion unterstützt (siehe auch Seite 704).
Der letzte Schritt ist die eigentliche Erstellung des Projekts. Hierbei nimmt KDevelop eine Vorlage für den von Ihnen ausgewählten Projekttyp und kopiert die Dateien zunächst in das Projektverzeichnis.
Am Anfang ist im Projekt noch kein Makefile vorhanden. Wenn Sie das erste Mal Ihr Projekt erstellen lassen (oder vorher den Menüpunkt ERSTELLEN — AUTOMAKE & KONSORTEN AUSFÜHREN auswählen), werden eine Konfigurationsdatei und eine Vorlage für ein Makefile erstellt. Bevor Sie es tatsächlich nutzen können, müssen Sie jedoch erst noch über den gleichnamigen Menüpunkt ein Hilfsprogramm aufrufen: ERSTELLEN — CONFIGURE AUSFÜHREN. Damit wird das Makefile an Ihre lokale Hard- und Softwareumgebung angepasst.
Alle Einstellungen, die das aktuelle Projekt betreffen, können Sie über den Dialog PROJEKT-OPTIONEN ansehen und bearbeiten; Sie erreichen ihn über den Menüpunkt PROJEKT — PROJEKT-EINSTELLUNGEN. Die Projektoptionen sind in mehrere Bereiche aufgeteilt, je nach darunter liegendem Werkzeug. Insgesamt wirken die Einstellungen ziemlich komplex. Allerdings brauchen Sie davon die meisten im Regelfall kaum. Ich will daher in diesem Rahmen auch nicht weiter auf die Details eingehen, sondern Sie an die - an dieser Stelle durchaus empfehlenswerte - KDevelop-Dokumentation verweisen.
Die Abhängigkeit von der lokalen Konfiguration lässt sich über die Datei config.h nutzen. Um dies einzusetzen, schreiben Sie an der Spitze Ihrer Codedateien die Zeilen
#include <config.h>
#endif
Die Vorgabe ist, dass sich die Funktion main() in einer Datei befindet, die
denselben Namen wie die Anwendung trägt. Bei kleineren Beispielen reicht
diese Datei bereits vollkommen aus. Wenn Sie weitere Dateien benötigen,
können Sie diese über DATEI — NEU erzeugen und auch gleich dem
Projekt hinzufügen.
Der Assistent hat bereits etwas Code in die Datei eingefügt: eine Ausgabe des berühmten "Hello World!" in der Form
#include <config.h>
#endif
#include <iostream>
#include <cstdlib>
using namespace std;
int main(int argc, char *argv[])
{
cout << ``Hello, World!`` << endl;
return EXIT_SUCCESS;
}
Es genügt, die Zeile mit cout zu entfernen und an deren Stelle Ihre Befehle
einzusetzen. Den Rest können Sie im Allgemeinen beibehalten, wenn das
jeweilige Beispielprogramm nichts anderes sagt.
Mit ERSTELLEN — PROJEKT ERSTELLEN oder der entsprechenden Schaltfläche beziehungsweise der Taste F8 lässt sich Ihr Programm übersetzen. Wenn Sie einen Fehler gemacht haben, den der Compiler moniert, so erscheint diese Meldung im Ausgabefenster unterhalb des Editors. Ein Doppelklick darauf genügt, und Sie landen wieder im Editor an der Stelle, die den Fehler verursacht hat.
Die Anwendung starten Sie mit ERSTELLEN — PROJEKT AUSFÜHREN
oder der Taste
+F9. KDevelop führt eine Konsolenapplikation auch in
einer Konsole aus. Es erscheint also ein Terminalfenster, in dem die
Ausgaben (oder auch Eingabeaufforderungen) Ihres Programms stehen.
Damit dieses Fenster nicht nach Programmende sofort wieder verschwindet,
ist eine Pausenfunktion eingebaut. Sie müssen zunächst die Eingabetaste
drücken, bevor es sich schließt.
Das Verzeichnis, in dem KDevelop die Quellen Ihrer Anwendung abgelegt hat, ist übrigens gut bevölkert. Der Assistent hat dort eine ganze Reihe von Dateien erzeugt, die alle mehr oder weniger wichtig sind, von denen Sie aber keine wirklich interessieren muss. Sie dienen alle dazu, die Automatismen, die Ihnen KDevelop bietet, zu unterstützen. Die eigentlichen Quellen Ihres Programms finden Sie im Unterverzeichnis src. Die ausführbare Datei finden Sie unter debug/src.
KDevelop setzt vollkommen auf offenen Standards auf. Wenn Sie also der Ansicht sind, dass dieses Werkzeug doch nicht das richtige für Sie ist, können Sie mit den generierten Dateien auch problemlos außerhalb von KDevelop weiterarbeiten. Mehr als make (siehe Seite 646) brauchen Sie dafür im Allgemeinen nicht.
Um ein Projekt unter die Fittiche von KDevelop zu stellen, gehen Sie folgendermaßen vor:
Nach diesen Schritten können Sie Ihr Projekt mit KDevelop übersetzen, bei Fehlern an die richtigen Stellen im Quelltext springen und den Debugger verwenden.
Zwei Aspekte sollten Sie jedoch von vornherein bei den Makefiles der Projekte beachten, die Sie später mit KDevelop bearbeiten wollen:
all hinzu, das sämtliche Zieldateien umfasst,
mindestens aber die ausführbare Datei.
clean enthalten, das die
Objektdateien und die sonstigen generierten Dateien löscht.
Dieses Ziel verwendet KDevelop, wenn Sie ERSTELLEN —
PROJEKT AUFRÄUMEN aufrufen.
Außerdem kann es Probleme beim Aufruf des Debuggers geben, der die ausführbare Datei nicht finden kann. In diesem Fall müssen Sie in den PROJEKT-EINSTELLUNGEN unter LAUFZEITOPTIONEN — HAUPTPROGRAMM den richtigen Dateinamen angeben.
Haltepunkte können Sie übrigens ganz einfach setzen, indem Sie über der jeweiligen Zeile aus dem Kontextmenü HALTEPUNKT EIN/AUS auswählen. Weitere Debugger-Kommandos können Sie über das Menü DEBUGGEN oder die entsprechenden Schaltflächen in der Werkzeugleiste geben.
Die Einstellungen für den Compiler sind in KDevelop etwas schwierig zu finden. Dazu müssen Sie nämlich erst den AUTOMAKE MANAGER (Symbol am rechten Rand des Editorfensters im IDEAl-Modus) öffnen und im oberen Teil das Unterprojekt src anklicken. Wenn Sie nun aus dem Kontextmenü dieses Eintrags den Punkt EINSTELLUNGEN wählen, gelangen Sie in einen Dialog, der es Ihnen erlaubt, Compiler-Schalter für den C- bzw. den C++-Compiler zu setzen. Sie können diese zum einen frei in das jeweilige Eingabefeld tippen. Wenn Sie sich aber nicht ganz sicher sind, wie der gesuchte Schalter heißt, können Sie zum anderen über die Schaltflächen mit den Pünktchen auch einen weiteren Dialog öffnen, in dem sich alle möglichen Einstellungen mit einem einfachen Mausklick erledigen lassen (Abbildung 7.8). Nach dem Schließen erscheinen dann in der zugehörigen Eingabezeile die notwendigen Compiler-Optionen.
Dennoch möchte ich in diesem Abschnitt versuchen, Ihnen den Start in die Welt der KDE-Anwendungen etwas zu erleichtern. Schritt für Schritt werden wir eine kleine Anwendung entwickeln, die Ihnen insbesondere die dafür nötigen Handgriffe mit KDevelop nahe bringen will.
![Gewicht [kg]
BM I = (Ko¨rpergr¨o¨se-[m])2](cpp_main81x.gif)
Werte zwischen 18.5 und 25 gelten dabei als Normalgewicht.
Unpraktisch am BMI ist, dass er sich nicht so leicht im Kopf errechnen lässt. Daher wollen wir in diesem Abschnitt ein Programm entwickeln, das nach der Eingabe von Größe und Gewicht den BMI bestimmt und noch ein paar Aussagen zu Risiken von Übergewicht macht. Letztere sollen abhängig vom Geschlecht der Person sein, so dass wir auch noch dafür eine Eingabemöglichkeit vorsehen müssen. Die Oberfläche der Anwendung soll also ungefähr wie in Abbildung 7.9 aussehen.
|
|
Die dahinter stehende Logik ist sehr einfach: Nach Eingabe der Daten und einem Klick auf die Schaltfläche AUSWERTUNG STARTEN wird die Plausibilität der Daten geprüft (um unsinnige Ergebnisse bei Eingabefehlern zu vermeiden), der Wert berechnet und anschließend zusammen mit einem Kommentar angezeigt.
Grafische Benutzeroberflächen arbeiten in mancherlei Hinsicht deutlich anders als alle sonstigen Anwendungsprogramme. Bei unseren bisherigen Programmen gab es meistens eine mehr oder weniger klare Linie, die von der Eingabe der Daten über die Verarbeitung bis zur Ausgabe geführt hat. Bei der Benutzeroberfläche gibt es eine solche Linie nicht.
Eine solches Programm muss sich stets dem Willen des Benutzers unterwerfen. Das bedeutet praktisch, dass es so lange warten muss, bis der Benutzer eine bestimmte Aktion macht, und dann darauf prompt zu reagieren hat. Die Reaktion kann dabei sehr unterschiedlicher Art sein. Bei einem Klick auf eine Schaltfläche SCHLIESSEN soll sich beispielsweise ein Fenster schließen, bei der Selektion eines bestimmten Werts in einer Liste sollen nur die Inhalte einiger anderer Elemente aktualisert werden usw. Wir haben es also mit einer ereignisgesteuerten Programmierung zu tun. Das bedeutet, dass bei den Steuerelementen bestimmte Ereignisse eintreten (entweder durch die Interaktion des Benutzers oder intern als Folge eines anderen Ereignisses) und als Reaktion darauf entsprechende Behandlungsroutinen aufgerufen und abgearbeitet werden.
Im Sinne der Objektorientierung - denn in Qt sind alle Steuerelemente echte C++-Objekte - heißt das, dass ein Objekt ein Ereignis signalisiert, wenn es seinen Zustand so geändert hat, dass dies für andere von Interesse sein könnte. Wer auf dieses Ereignis reagiert und was daraufhin getan wird, ist für das Objekt selbst nicht von Bedeutung. Umgekehrt kann eine Behandlungsroutine auch durch verschiedene Arten von Ereignissen ausgelöst werden. Beispielsweise soll ja beim Klick auf ein Symbol der Werkzeugleiste und bei der Auswahl des entsprechenden Menüpunktes jeweils dieselbe Aktion ausgeführt werden.
Solche Ereignisse bezeichnet man in Qt als Signale. Ein Objekt sendet ein Signal aus, wenn sich bei ihm etwas ändert. Wenn sich ein anderes Objekt für dieses Signal angemeldet hat, wird dessen Behandlungsroutine aufgerufen. Gibt es keinen Interessenten, passiert auch nichts. Ein Signal ist eine Methode der Klasse, die auch Parameter haben kann. Zudem kann das aussendende Objekt noch zusätzliche Informationen über das Ereignis mitgeben. Viele Klassen in Qt haben bereits Signale vordefiniert; durch Ableiten können Sie aber jederzeit neue hinzufügen.
Eine Methode zum Behandeln von Signalen bezeichnet man bei Qt als
Slot. Ein Slot entspricht in der Signatur dem Ereignis, auf das er
reagieren soll (er darf genau genommen aber auch weniger Parameter
haben). Er wird dann aufgerufen, wenn das Ereignis eintritt, mit
dem er verbunden ist. Natürlich können Sie eine Slot-Methode auch
wie jede andere C++-Methode aufrufen. Meistens wird man solche
Methoden als public slots deklarieren, damit auch die Signale anderer
Objekte damit verbunden werden können. Es ist aber möglich, diese
auf protected slots oder gar private slots einzuschränken. Jedes
Qt-Objekt, das von einem Typ ist, der von QObject abgeleitet ist (wie
das alle grafischen Steuerelemente sind), kann Signale und Slots
beinhalten.
Wie findet nun das Signal seinen Slot? Anders als bei anderen GUI-Bibliotheken setzt Qt hierbei auf eine sehr lose Kopplung. Die Verbindung ist weder Teil des aussendenden noch des empfangenden Objekts, sondern wird separat festgelegt. Dadurch ist es aber sehr bequem möglich, einem Signal verschiedene Slots zuzuordnen oder aber einen Slot zur Behandlung mehrerer Signale zu verwenden. Die Objekte selbst wissen darüber nichts.
Wenn Sie sich jetzt fragen, ob Sie das alles auch so selbst programmieren müssen, kann ich Sie beruhigen. Der Qt-Designer, mit dem wir später die grafischen Elemente entwerfen werden, unterstützt Sie beim Setzen von Slots und beim Zuordnen zu Signalen durch entsprechende Dialoge. Mit ein paar Klicks sind die passenden Verbindungen hergestellt. Der Rest wird automatisch erledigt.
Trotzdem möchte ich Ihnen zur Illustration etwas vom generierten
Code zeigen, damit Sie das Konzept besser verstehen. Unser Dialog
aus Abbildung 7.9 beinhaltet ein Objekt namens pbEval vom Typ
QPushButton. Diese Klasse hat keine eigenen Signale definiert;
sie stehen in ihrer Basisklasse QButton. Signale deklariert man
mit Hilfe des speziellen Schlüsselworts signals, Slots mit public slot
usw.
Qt-Klassen beginnt man zudem im Allgemeinen mit dem Makro
Q_OBJECT, das eine Reihe von Standardmethoden deklariert. Die Klasse
QButton sieht damit etwa wie folgt aus (ich habe allerdings viele
Bestandteile gelöscht, um Ihnen die Übersicht zu erleichtern; andere
Bestandteile hatte wir ja schon in Abschnitt 2.4.1 ff. immer wieder mal
besprochen):
{
Q_OBJECT
public:
QButton( QWidget* parent=0,
const char* name=0, WFlags f=0 );
~QButton();
QString text() const;
virtual void setText( const QString &);
signals:
void pressed();
void released();
void clicked();
protected:
virtual void drawButton( QPainter * );
void keyPressEvent( QKeyEvent *);
void keyReleaseEvent( QKeyEvent *);
private slots:
void animateTimeout();
void autoRepeatTimeout();
private:
QString btext;
friend class QButtonGroup;
// ...
};
Das Signal kommt also direkt vom Button; den Slot ordnen wir dem Formular zu (also der Klasse für das Hauptfenster), da über dieses die gesamte Interaktion abgewickelt werden soll. Meist ist es sinnvoll, Slots, die Signale von Steuerelementen auf einem Formular behandeln sollen, innerhalb der Formularklasse zu definieren. Da wir uns das Codegerüst aber automatisch erzeugen lassen wollen, verschieben wir die Implementierung noch etwas.
Die Verbindung zwischen Signal und Slot wird im Konstruktor des Formulars hergestellt, wo auch alle Steuerelemente angelegt und konfiguriert werden. Auch dieser Code wird automatisch erzeugt, so dass kein Eingriff von Ihnen erforderlich ist.
Bei den Qt-spezifischen Schlüsselwörten wie signals handelt es sich
nicht um Spracherweiterungen von C++, sondern nur um sehr geschickt
angelegte Makros. Aus Gründen der Flexibilität und Portabilität setzt Qt
hierbei auf einen zusätzlichen Präprozessor, den Meta-Object-Compiler
moc. Dieser MOC wird auf alle Header-Dateien angewendet, die Klassen
mit einer Q_OBJECT-Deklaration enthalten. Er löst die Makros auf
und erzeugt daraus Standard-C++-Code. Die daraus entstandenen
Dateien werden mit den anderen Projektdateien übersetzt und zum
Gesamtprogramm verlinkt. Wenn Sie mit Entwicklungsumgebungen wie
KDevelop arbeiten, bleiben diese Vorgänge weitgehend vor Ihnen verborgen
- alles läuft automatisch ab. Sie merken nur, dass sich am Ende in Ihrem
Quellverzeichnis ein paar mehr C++-Dateien befinden, als Sie selbst
geschrieben haben.
|
|
Wenn Sie schon mit anderen Werkzeugen wie Visual Basic oder Delphi gearbeitet haben, wird Ihnen das Konzept bekannt vorkommen: eine Werkzeugleiste mit Komponenten, ein Editor für Eigenschaften und Ereignisbehandlungsroutinen sowie Möglichkeiten zur Formatierung und Vorschau.
PushButton1 lassen Sie sehr schnell den
Überblick über die eigentliche Bedeutung der Elemente verlieren.
GroupBoxes und Ähnlichem.
Um Ihnen einen Überblick über die Zugehörigkeiten und andere
Objekteigenschaften zu geben, bietet Qt-Designer den Object
Explorer an. (Sollte dieser nicht von Anfang an sichtbar sein,
können Sie ihn über WINDOW — VIEWS — OBJECT EXPLORER
zum Vorschein bringen.) Ein Objekt, das Sie dort markieren,
ist dann auch im Formular-Designer und im Eigenschaftseditor
ausgewählt.
Um die Oberfläche für ein Programm wie in unserem Beispiel mit KDevelop und dem Qt-Designer zu entwerfen, gehen Sie folgendermaßen vor:
Nun geht es an die Gestaltung des Formulars. Bevor Sie sich für diese
Aufgabe an den Rechner setzen, sollten Sie bereits eine möglichst konkrete
Vorstellung davon haben, welche Bedienelemente darauf vorkommen und
wie diese zueinander angeordnet werden sollen. Achten Sie darauf, dass
Ihre Dialoge nicht zu überladen sind, denn dies kann für den Benutzer sehr
schnell unübersichtlich und undurchschaubar werden. Wenn Sie mehr
Steuerelemente benötigen, als auf Ihr Formular passen, verwenden
Sie besser ein TabWidget, mit dem sich zwischen verschiedenen
"Teil-Formularen" blättern lässt.
Für das Fenster aus Abbildung 7.9 (Seite 782) benötigen wir aber nur einige wenige grafische Elemente. Ich möchte Ihnen hier nicht jeden Schritt im Detail erläutern, sondern nur ein paar Eckpunkte geben, anhand derer Sie ein solches Formular sicher schnell selbst erstellen können - wenn Sie das möchten. Dabei verwende ich sprachlich vorwiegend die englischen Ausdrücke für Ihre bessere Orientierung im Qt-Designer; verzeihen Sie mir also das etwas zu "anglophile" Deutsch hier.
sizePolicy
Fixed bei einer maximumSize von 360, 385.
hAlign ist AlignRight) und heißen
leHeight beziehungsweise leWeight.
-Taste) und LAYOUT —
LAY OUT IN A GRID wählen.
autoDefault als auch default auf true gesetzt.
hAlign steht auf AlignHCenter
und vAlign auf AlignVCenter). Darunter ist ein Textedit-Feld
mit dem Namen teTextbox, das auf readOnly gesetzt ist; hier soll
die textuelle Auswertung angezeigt werden.
Aufgrund der fixierten Größe des Formulars benötigen wir eigentlich keine Hilfsmittel wie Spacer und Layoutrahmen. Versuchen Sie aber trotzdem schon bei einfachen Formularen wie hier diese Funktionen einzusetzen, damit Sie ein Gefühl für deren Wirkungsweise bekommen. Es handelt sich dabei um sehr effektive Gestaltungsmittel für die flexible Anpassung an Veränderungen der Fenstergröße. Generell sollten Sie dabei zunächst die horizontale Anordnung im Auge behalten, bevor Sie sich um die vertikale kümmern. Am besten ist es, wenn Sie die Wirkung von Spacern und Layout in verschiedenen Varianten mit Hilfe der PREVIEW-Funktion ausprobieren.
Nach Abschluss des Designs müssen wir noch den Klick auf die
AUSWERTUNG STARTEN-Schaltfläche mit der eigentlichen Auswertung
verbinden. Bei einem Qt-Formular bedeutet das, das Signal clicked mit
einem entsprechenden Slot zu verbinden (siehe auch Seite 783).
Um eine solche Verbindung zu erstellen, müssen Sie zunächst in
den entsprechenden Modus wechseln, zum Beispiel mit TOOLS —
CONNECT SIGNALS/SLOTS oder einfach mit F3. Dadurch wird der
Mauszeiger zu einem Kreuz. Eine Verbindung stellen Sie her, indem Sie
auf das signalerzeugende Steuerelement (bei uns der PushButton)
klicken und die nun erscheinende Linie zum Widget ziehen, das
den Slot dafür beinhalten soll. Beim Herumfahren mit der Maus
werden Sie sehen, dass Letzteres durch einen violetten Rahmen
markiert wird. Bei Dialog- und Hauptprogrammfenstern definiert man
die Slots für die Reaktionen auf Schaltflächen und Ähnliches im
Allgemeinen in der Formularklasse. Das wollen wir auch hier tun. Ziehen
Sie also die Verbindungslinie über die freie Fläche des Formulars
aus diesem hinaus und lassen Sie die linke Maustaste dann erst
los.
Nun öffnet sich ein Dialog wie in Abbildung 7.11, mit dem Sie die Details dieser Verbindung festlegen können.
Wir wollen eines der vordefinierten Signale des Pushbuttons verwenden,
nämlich clicked(). Dieses wird ausgelöst, wenn der Benutzer die
Schaltfläche einmal anklickt. Um aber flexibel zu bleiben, wollen wir zur
Behandlung selbst einen Slot definieren. Wählen Sie dazu zunächst
clicked() als das zu behandelnde Signal aus, indem Sie die zweite Spalte in
der Tabelle anklicken und in der herunterklappbaren Liste diesen Begriff
selektieren. Mit einem weiteren Klick auf EDIT SLOTS öffnen Sie einen
zusätzlichen Dialog, der Ihnen alle definierten Slots der jeweiligen
Formular- oder Steuerelementklasse anzeigt. Im Augenblick ist die Liste
noch leer. Mit NEW FUNCTION fügen Sie einen neuen Slot hinzu, dem Sie
im Eingabefeld FUNCTION den Namen calcSlot() geben können
(siehe Abbildung 7.12). Die übrigen Einstellungen können Sie auf
den Vorgabewerten belassen. Wenn Sie nun dieses Fenster mit OK
schließen, erscheint der neue Slot in der Liste oben rechts im EDIT
CONNECTIONS-Dialog.
Damit können wir diesen Dialog schließen und sind mit dem Design unserer GUI fertig. Bei komplexeren Anwendungen werden Sie sicher weitere Steuerelemente haben, mehrere Signale behandeln und umfangreichere Slots definieren - die Vorgehensweise, die ich Ihnen anhand dieses simplen Beispiels gezeigt habe, bleibt aber die gleiche.
Als Nächstes müssen wir die gerade entworfene Benutzerschnittstelle mit
dem bereits vorhandenen Gerüst unserer Anwendung zusammenbringen.
Dazu ersetzen wir am besten die vorher erzeugte Klasse Bmi durch eine
neue, die wir als Ableitung unseres Formulars erhalten. Und das geht
so:
Bmi
genommen.
Bmi
angelegt. Diese ist direkt von BmiMainForm, unserem Formular,
abgeleitet, und enthält auch schon einen Rumpf für die Methode
calcSlot(). Den müssen wir jetzt nur noch ausfüllen.
|
|
Zunächst einmal sollten wir aber noch die main()-Methode etwas anpassen.
In der automatisch erzeugten Form ist sie auf deutlich komplexere
KDE-Anwendungen ausgerichtet. Daher müssen wir einige Zeilen
entfernen. Reduzieren Sie die zweite Hälfte dieser Funktion so, dass nur
noch folgende Zeilen übrig bleiben:
Bmi *mainWin = 0;
mainWin = new Bmi();
app.setMainWidget( mainWin );
mainWin->show();
return app.exec();
}
Da unsere Anwendung recht simpel ist, sind wir nun bereits beim letzten
Arbeitsschritt angelangt: der Implementierung von calcSlot(). Hier müssen
wir erstmals von einem Programm aus direkt auf die Steuerelemente auf
dem Formular zugreifen, denn wir wollen die Eingaben des Benutzers
verarbeiten und Ausgaben erzeugen. Dazu ein paar grundlegende
Bemerkungen:
BmiMainForm eingegangen. Es ist dort
ein Zeiger auf ein Objekt vom Typ dieses Steuerelements.
Beispielsweise ist die Eingabezeile für das Körpergewicht
deklariert als QLineEdit*, also Zeiger auf ein QLineEdit-Objekt,
mit dem Namen leWeight. Wenn Sie also auf seine Attribute
und Methoden zugreifen wollen, nehmen Sie dazu am besten den
Pfeiloperator -¿.
QLineEdit::text() ein
QString-Objekt zurück. Wenn wir dessen Inhalt in eine
Fließkommazahl umwandeln wollen, wie wir es bei der
BMI-Berechnung etwa für das Gewicht benötigen, müssen wir die
Methode QString::ToFloat() dieses Objekts aufrufen. Zusammen
sieht das dann so aus:
Q...
beginnen).
Mit diesem Wissen im Hinterkopf ist die Fertigstellung der Implementierung
unseres Beispielprogramms nicht mehr schwierig. Zunächst wandeln wir wie
gerade beschrieben die Eingaben in float-Zahlen um und prüfen deren
Plausibilität:
{
float height = (leHeight->text()).toFloat();
float weight = (leWeight->text()).toFloat();
if (height < 50 || height > 300)
{
Bei einer Körpergröße von weniger als 50 cm oder mehr als 300 cm gehen
wir von einem Eingabefehler aus (beispielsweise eine Eingabe in m). In
diesem Fall weisen wir den Benutzer über eine QMessageBox, ein
Nachrichtenfenster, darauf hin.
"Bitte geben Sie die Größe in cm an!",
QMessageBox::Warning,
QMessageBox::Ok | QMessageBox::Default,
QMessageBox::NoButton,
QMessageBox::NoButton);
mb.exec();
return;
}
Analog wollen wir ein Gewicht von unter 20 kg und über 1000 kg nicht mehr als gültige Eingabe akzeptieren. Der Programmcode ist dabei fast der gleiche wie oben, so dass ich hier auf einen Abdruck verzichte.
Nun können wir den BMI berechnen und in das dafür vorgesehene
Label schreiben. Dabei leistet die Methode QString::sprintf() gute
Dienste, die für die formatierte Ausgabe dasselbe Format wie die
C-Funktion sprintf() akzeptiert. In diesem Fall wollen wir uns auf eine
Nachkommastelle beschränken.
float bmi = weight/(height*height);
QString s;
s.sprintf("Ihr BMI ist %.1f", bmi);
lBmi->setText(s);
Als Letztes wollen wir noch einen Hinweistext über Gesundheitsgefahren
durch Übergewicht in unserem QTextEdit-Feld in Abhängigkeit
vom Geschlecht ausgeben. Die verschachtelten if-Anweisungen sind
programmiertechnisch nicht so interessant, so dass es genügen sollte, wenn
ich Ihnen hier die ersten Zeilen vorstelle:
{
s = "Sie haben Untergewicht.";
}
else
if (bmi < 25)
{
s = "Sie haben Normalgewicht. ";
if (rbMale->isChecked())
s += "Keinerlei Risiko.";
else
{
s += "Keine Gefahr für Diabetes und Herz";
s += "krankheiten, außer bei zu viel Fett.";
}
}
else
// Weitere Fallunterscheidungen
// ...
Diesen Info-Text geben wir nun noch aus und sind damit am Ende dieser Methode.
return;
}
Zur Vervollständigung müssen wir nur noch die Klassen zu den hier von uns verwendeten Objekten deklarieren, d.h. deren Header-Dateien einbinden. Im oberen Bereich der Datei bmi.cpp fügen wir also ein:
#include <qlabel.h>
#include <qlineedit.h>
#include <qtextedit.h>
#include <qradiobutton.h>
#include <qmessagebox.h>
Jetzt ist es an der Zeit, dass wir unsere Anwendung übersetzen. Dies sollte nun eigentlich problemlos möglich sein. Nachdem wir aber viel an der Projektstruktur verändert haben, ist es zunächst notwendig, ERSTELLEN — AUTOMAKE & KONSORTEN AUSFÜHREN sowie anschließend ERSTELLEN — CONFIGURE AUSFÜHREN aufzurufen. Danach können Sie mit F8 das Projekt übersetzen und mit DEBUGGEN — START ausführen.
Sie sollten aber auf jeden Fall anhand dieses Beispiels die grundsätzliche Vorgehensweise beim Erstellen einer KDE/Qt-Anwendung mit KDevelop erkannt haben. Wenn Ihnen dann der Umgang mit der IDE keine Probleme mehr bereitet, können Sie sich voll und ganz auf die Entwicklung von Dialogen und komplexeren Applikationen mit den verschiedensten Qt-Objekten konzentrieren. Mit weiteren Büchern wie [HEROLD 2001] oder [LEHNER 2001] können Sie bei Interesse und Bedarf noch viel über Qt erfahren.
Alles in allem ist KDevelop eine umfangreiche und stabile Entwicklungsumgebung, die fast alles liefert, was man als Programmierer benötigt. Sie ist damit sowohl für den Anfänger als auch für den Profi sehr empfehlenswert. Da die Entwicklung daran aber immer noch mit Nachdruck weitergeht, werden wir sicher noch viele interessante neue Funktionselemente im Lauf der Zeit zu sehen bekommen.
man-Seite dazu studieren, werden Sie feststellen, dass dieses
Werkzeug über ziemlich viele Optionen verfügt. Ihre Aufgabe ist
es nun, eine Qt-Anwendung zu schreiben, die eine grafische
Benutzerschnittstelle für a2ps darstellt. Sie soll folgende Elemente
enthalten:
Go und
Close angeordnet sein. Klickt der Benutzer auf Go, so soll
a2ps mit den eingestellten Optionen aufgerufen werden. Bei
Close soll sich die Anwendung beenden.
du
-sk /verzeichnis heranziehen.)
Eine der neuesten und viel beachteten integrierten Entwicklungsumgebungen unter Linux ist Eclipse. Es handelt sich dabei um ein Produkt basierend auf der ehemaligen Visual Age-Familie von IBM, das die Firma im November 2001 als Open Source freigegeben hat. Seitdem wird Eclipse von einer über 1200 Entwickler starken Community, zu der auch namhafte Firmen wie Merant, QSSL, Rational, Red Hat und TogetherSoft gehören, mit großem Nachdruck weiterentwickelt. Ausführliche Informationen und die neuesten Releases erhalten Sie von der Projekt-Website www.eclipse.org.
Eclipse möchte daher nicht einfach ein weiteres Tool sein, sondern eine universelle Plattform, über die die verschiedenen Werkzeuge benutzt werden können. Es handelt sich bei Eclipse also mehr um eine generische IDE, in die durch einen Plug-in-Mechanismus viele andere Werkzeuge eingebunden werden können, darunter auch eine IDE zur C++-Programmierung. Als Benutzer sollten Sie kaum merken, wie die verschiedenen Tools ineinander greifen (siehe dazu auch [BORZECHOWSKI 2004] oder [DAUM 2003]).
Als echtes Open-Source-Projekt (unter einer Apache-ähnlichen Lizenz) verfügt Eclipse über völlig offene Schnittstellen, die es jedem ermöglichen, eigene Beiträge für die Plattform zu schaffen. Und wie bei vielen anderen Open-Source-Projekten dauert es auch etwas, bis ein Reifegrad erreicht ist, der einen tatsächlichen Einsatz in der Praxis möglich macht. Da Eclipse selbst vorwiegend in Java geschrieben ist, wundert es nicht, dass die Unterstützung für Java am weitreichendsten ist. Zusammen mit Eclipse 3 erschien aber auch die Version 2.0 der C/C++ Development Tools (CDT), die damit einen sehr stabilen und brauchbaren Zustand erreicht haben (siehe auch www.eclipse.org/cdt). Durch dieses Plug-in ist die Entwicklung von C++-Programmen mit Eclipse sehr einfach möglich. Die CDT umfassen einen Editor mit syntaxabhängiger Einfärbung, eine grafische Schnittstelle zum gdb für das Debugging, eine Kommandozeilenschnittstelle zum normalen Starten von Anwendungen, einen Parser, eine Suchmaschine sowie einen Generator für Make-Dateien.
Die Eclipse-Plattform setzt sich aus folgenden Bestandteilen zusammen:
Die gesamte grafische Oberfläche von Eclipse ist mit Hilfe von SWT programmiert. Es handelt sich dabei um eine Bibliothek von grafischen Komponenten (den so genannten "widgets", was für "window gadgets", also Fensterelemente, steht). Sie ist selbst in betriebssystemabhängiger Form entwickelt, das heißt, sie nutzt die Möglichkeiten des jeweiligen Fenstersystems (Windows, Motif etc.), bietet aber eine unabhängige Programmierschnittstelle (API) an. Entwickler können damit Benutzerschnittstellen schreiben, die genauso unter Linux wie unter Windows und anderen Betriebssystemen laufen. Anders als etwa das AWT-Toolkit von Java versucht SWT, eine große Vielfalt von Steuerelementen zur Verfügung zu stellen, wobei im Allgemeinen die Controls des jeweiligen Fenstersystems genutzt werden; ist ein solches jedoch nicht vorhanden, bietet SWT eine Emulation.
Um die Programmierung von GUIs unter Java noch weiter zu vereinfachen, bildet JFace noch eine Abstraktionsschicht über SWT. JFace enthält Komponenten für die Auswahl von Bildern und Zeichensätzen, Baukästen für Dialoge und Assistenten sowie Fortschrittanzeigen. Darüber hinaus stellt es Möglichkeiten für die Gestaltung interaktiver Betrachter (Viewer) zur Verfügung.
Die Installation von Eclipse ist sehr einfach. Zunächst müssen Sie sich bei Linux aber für eine der zwei Varianten entscheiden: Linux mit GTK (GIMP Toolkit) oder Linux mit Motif. Bei beiden Zusätzen handelt es sich um Bibliotheken, die für die grafische Darstellung der Fenster und Steuerelemente verantwortlich sind. Das bessere optische Ergebnis erhalten Sie meines Erachtens mit GTK; wenn Sie also die GTK-Version 2.2.1 oder höher (sowie die davon wiederum benötigten Bibliotheken) installiert haben, sollten Sie die GTK-Variante bevorzugen. Der Vorteil der Motif-Version ist, dass dabei die Grafikbibliothek (OpenMotif 2.1) schon in Eclipse enthalten ist.
Zur eigentlichen Installation müssen Sie lediglich das heruntergeladene
Archiv in ein Verzeichnis auspacken (zum Beispiel nach /opt/) und
Ihre path-Variable darauf setzen. Die Unterstützung für C++
befindet sich in einem separaten Plug-in, das einen Namen trägt wie
org.eclipse.cdt-2.0-linux.gtk.x86.zip und das Sie ebenfalls herunterladen
und auspacken müssen. Es enthält bereits die Pfadangaben zu den
nötigen Unterverzeichnissen, so dass Sie es nur noch in dasselbe
Hauptverzeichnis extrahieren müssen, in dem auch Eclipse liegt, also
beispielsweise:
Sollte sich Eclipse nicht starten lassen, kann das an Problemen mit Java
liegen. Da Eclipse bis auf das Startprogramm vollständig in Java
geschrieben ist, wird ein installiertes Java Runtime Environment (1.4.1
oder höher) vorausgesetzt. Es muss entweder über die Pfadvariable
erreichbar sein oder über die Kommandozeilenoption -vm ¡vm_path¿
angegeben werden.
Beim Start werden Sie außerdem gefragt, in welchem Verzeichnis Sie Ihre Projekte abspeichern wollen. Dieses Verzeichnis heißt bei Eclipse auch Workspace. Für jedes einzelne Projekt wird darin später ein Unterverzeichnis angelegt.
Nach dem Start fällt als Erstes die Aufteilung des Hauptfensters in verschiedene Teilbereiche auf (siehe Abbildung 7.14). Es repräsentiert die verschiedenen Werkzeuge, die zum Startzeitpunkt geladen sind. Bei der Standardinstallation finden Sie auf der linken Seite die C/C++-Projektverwaltung, aus der Sie erkennen können, welche Dateien zu Ihrem Projekt gehören. Wenn Sie die Dateien aus der Projektliste weiter aufklappen, sehen Sie nicht nur, welche Klassen und Funktionen enthalten sind, sondern auch, von welchen anderen Dateien, insbesondere Header-Dateien, die jeweilige Datei abhängt. Über das Kontextmenü können Sie zudem Dateien importieren und exportieren, löschen und hinzufügen, umbenennen und kopieren. Auf der rechten Seite fällt der so genannte Outline-View auf, der die Struktur der gerade bearbeiteten Klasse widerspiegelt. Damit können Sie beispielsweise leicht im Editor zu den verschiedenen Methoden der Klasse springen. Im unteren Bereich befinden sich schließlich noch die Ausgabefenster, also etwa die Konsolenausgabe sowie die Liste der Fehlermeldungen.
Im Zentrum jeder IDE steht jedoch der Editor. Syntaxeinfärbung beherrscht der Eclipse-Editor für C++ recht gut. Interessant sind auch die Möglichkeiten zur automatischen Codeformatierung, die jedoch für Java schon weiter entwickelt sind als für C++. Von KDevelop kennen wir bereits die Codevervollständigung, die auch hier zum Teil gute Dienste leistet (erreichbar über das Kontextmenü oder Strg+Leertaste).
Ein ebenso bekanntes wie hilfreiches Funktionsmerkmal sind die
Codeschablonen. Wenn Sie ein Strukturelement wie for, if (...) else oder
catch einfügen wollen, so genügt es, das jeweilige Schlüsselwort einzugeben
und dann Strg+Leertaste zu drücken. Dann können Sie aus der Auswahl
die passende Schablone entnehmen. Bei einer for-Schleife etwa erscheint
gleich der komplette Schleifenrumpf:
}
Besonders praktisch ist: Wenn Sie nun den Namen der Schleifenvariable var
ändern, ändert er sich automatisch an den anderen zwei Positionen mit.
Eine vollständige Liste aller zur Verfügung stehenden Schablonen - mit der
Möglichkeit, eigene hinzuzufügen - finden Sie unter WINDOW —
PREFERENCES — C/C++ — CODE TEMPLATES.
Interessant sind auch die so genannten Perspektiven. Diese kleinen Symbole rechts oben stellen verschiedene Sichten auf die IDE dar, wobei die Werkzeugfenster, welche man Views nennt, jeweils in unterschiedlichen Größen und Anzeigeformen auftauchen. Auf diese Weise können Sie je nach dem Arbeitsschritt, an dem Sie gerade sind, die für Sie angenehmste Kombination an Werkzeugen definieren. Über den Punkt WINDOW — CUSTOMIZE PERSPECTIVE können Sie die Perspektiven relativ frei konfigurieren.
Für C++ sind dabei drei Perspektiven vorkonfiguriert: Die Standard-C++-Perspektive mit dem Projektnavigator und dem Outline-Fenster (Abbildung 7.14), die Debugging-Perspektive, in der alle Debug-Informationen vom Aufrufstapel über die Werte der lokalen Variablen bis zur Konsolenausgabe dargestellt werden (Abbildung 7.18 auf Seite 829), sowie die C/C++-Browsing-Perspektive. In dieser (Abbildung 7.15) sind im oberen Drittel Navigations-Views, mit denen Sie sich innerhalb der Klassen und Methoden Ihres Projekts bewegen können. Wählen Sie zunächst ganz links ein Projekt, dann daneben einen Namespace daraus, aus diesem wiederum eine Klasse oder Struktur, dann können Sie schließlich ganz rechts eine Liste mit den Attributen und Methoden dieses Datentyps sehen. Wenn Sie auf eine davon klicken, erscheint die Datei mit deren Deklaration im darunter liegenden Editorfenster.
|
|
Noch ein Tipp: Wenn Sie eine bestimmte Klasse, ein enum oder ein
typedef suchen, können Sie entweder NAVIGATE — OPEN TYPE wählen,
was Sie zu dessen Deklaration führt. Oder aber Sie starten mit SEARCH —
C/C++ gleich die sprachspezifische Suche, die Ihnen neben der
Deklaration auch die Definition und sogar die Referenzierungen darauf
heraussucht.
Wenn Sie das C++-Development-Toolkit erfolgreich installiert haben, finden Sie in der Auswahlliste auch C/C++, das Ihnen nach dem Aufklappen zwei Möglichkeiten zur Wahl stellt: MANAGED MAKE C++ PROJECT oder STANDARD MAKE C++ PROJECT. Der Unterschied ist simpel: Beim Standard-Make-Projekt müssen Sie Ihre Make-Dateien selbst schreiben und verwalten, beim Managed-Make-Projekt nimmt Eclipse Ihnen diese Arbeit ab.
Geben wir unserem Projekt also mal den Namen Beispiel1.
Wenn Sie schon ein bestehendes klassisches C++-Projekt - mit Dateien und einem Makefile - haben, können Sie es mit FILE — IMPORT auch zu Ihrem gerade angelegten Eclipse-Projekt hinzufügen. Allerdings sollten Sie dazu als Typ FILE SYSTEM angeben; mit EXISTING PROJECTS sind nur Eclipse-Projekte gemeint. Wenn Sie auch das Makefile importieren wollen, müssen Sie vorher das Projekt als Standard-Make-Projekt angelegt haben. Nach der Auswahl eines Verzeichnisses haben Sie übrigens die Möglichkeit anzugeben, welche Dateien in diesem Verzeichnis übernommen werden sollen und welche nicht.
Noch ist unser Projekt aber völlig leer. Wir müssen daher als Nächstes eine Quelltextdatei hinzufügen.
Nun können Sie den Quelltext von Seite 95 hier eingeben.
Bei C++ kann das ein wenig anders sein: Eine etwas größere C++-Datei kann durchaus - je nach Rechnergeschwindigkeit - 15 bis 30 Sekunden zum Kompilieren benötigen. Wenn diese Wartezeit bei jedem Speichern anfällt, kann das leicht nerven. Deshalb gibt es auch die Möglichkeit, das automatische Kompilieren abzuschalten, nämlich über den Menüpunkt PROJECT — BUILD AUTOMATICALLY. Wenn dieser nicht mehr angekreuzt ist, entfällt die Wartezeit. Und es erscheint ein Schalter BUILD ALL auf der Werkzeugleiste sowie als Menüpunkt im PROJECT-Menü.
Solange wir den Automatismus aber noch aktiviert haben, müssen wir das Kompilieren nicht von Hand starten. Wenn Sie alles richtig eingegeben haben, sollte also das ausführbare Programm zur Verfügung stehen.
Beim zweiten Start können Sie auf die erzeugte Konfiguration zurückgreifen und nur über die Schaltfläche mit dem grünen Pfeil die Anwendung starten.
|
|
Sollte Eclipse beim Starten der Anwendung mal hängen bleiben, etwa weil es noch auf eine Kompilierung wartet, die in Wirklichkeit schon längst abgeschlossen ist, so können Sie durch Klick auf das rote Quadrat in diesem Fenster den Vorgang auch abbrechen. Die Anwendung ist dann aber immer noch nicht gestartet. Dazu wählen Sie in diesem Fall RUN — RUN AS — C LOCAL APPLICATION.
Nun hat sich das Aussehen der Oberfläche deutlich gewandelt (Abbildung 7.18). Oben links sehen Sie den Aufrufstapel. Da wir nur ein einfaches Programm mit einer Funktion haben, ist er hier nicht so kompliziert. Im selben View finden Sie aber auch die Schaltflächen für den Programmfortschritt. Natürlich lässt sich das auch mit Funktionstasten erledigen:
In der Mitte finden Sie den augenblicklich zu durchlaufenden Code. Im View links oben stehen die Werte der Variablen. Und ganz unten ist ein Konsolen-View, der die Bildschirmausgabe des Programms und des Debuggers zeigt.
|
|
Falls Sie noch weitere Details über Ihr Programm wissen möchten, können Sie diese über WINDOW — SHOW VIEW öffnen. Probieren Sie einfach mal aus, was Sie dabei alles in Erfahrung bringen können.
Nach Beendigung des Programms erscheint der Status terminated im
Debug-View. Trotzdem bleibt die Debugging-Perspektive erhalten.
Natürlich unterstützt Eclipse auch das Versionsverwaltungssystem CVS (siehe auch Seite 707). Es bildet dabei eine ebenso übersichtliche wie leicht zu bedienende grafische Benutzerschnittstelle.
Zunächst muss der Zugriff auf das CVS-Repository eingerichtet werden. Auch dafür stellt Eclipse wieder einen passenden View bereit.
Wenn nun die Verbindung auch zustande kommt, können Sie die Module und Zweige Ihres Repository im entsprechenden View sehen.
Als Nächstes können Sie entweder Ihr bestehendes Projekt zum Repository hinzufügen oder ein dort bereits vorhandenes auschecken, um an diesem weiterzuarbeiten. Gehen wir zunächst vom ersten Fall aus. Dazu öffnen Sie im Navigator (linke Leiste) das Kontextmenü des Projekts und wählen daraus den Eintrag TEAM — SHARE PROJECT. Sie werden dann gefragt, welches Repository Sie verwenden wollen und ob Sie einen anderen Modulnamen als den Projektnamen vergeben möchten. Wenn Sie den Vorgang dann mit FINISH abschließen, werden alle Ihre veränderbaren Projektdateien in das Repository übertragen.
Um mit der Weiterarbeit an einem Projekt zu beginnen, das zwar schon im CVS-Repository, aber noch nicht lokal vorhanden ist, öffnen Sie das Kontextmenü dieses Projekts im Repository-View und wählen dort CHECK OUT AS. Nun können Sie sich entscheiden (Abbildung 7.20), ob Sie das Projekt als neues Projekt in den lokalen Workspace einfügen möchten, in ein bestehendes eingliedern wollen usw.
|
|
Nachdem Sie ein lokales Projekt mit einem aus dem Repository verbunden haben, ändert sich sowohl das TEAM-Kontextmenü des Projekts als auch das der enthaltenen Dateien. Um das Projekt abzurufen, das heißt lokale unveränderte Dateien gegebenenfalls durch neuere aus dem Repository zu ersetzen, wählen Sie TEAM — UPDATE. Daraufhin öffnet sich der Synchronize-View, dem sogar eine eigene Perspektive zugeordnet ist. In diesem können Sie erkennen, welche Dateien sich von Ihrem lokalen Stand unterscheiden. Hier haben Sie auch die Möglichkeit, etwaige Konflikte mit Ihren Änderungen zu erkennen und diesen entgegenzuwirken.
Die Update-Aktion sollte immer einem Einchecken vorausgehen. Nach der Synchronisation müssen Sie überprüfen, ob die dadurch hinzugekommenen Änderungen noch zu dem von Ihnen hinzugefügten Code passen - zunächst durch einfaches Kompilieren, besser aber durch zusätzliche Testprogramme.
Wenn Ihr Code zusammen mit den synchronisierten Dateien fehlerfrei läuft, können Sie ihn einchecken ("committen"). Dazu rufen Sie aus dem Kontextmenü des Projekts oder einer Datei den Punkt TEAM — COMMITT auf. Daraufhin werden Sie aufgefordert, einen Kommentar zu diesen Änderungen einzugeben. Anschließend überträgt Eclipse die Datei(en) an den CVS-Server.
Das flexbile Plug-in-Konzept, das zudem durch die Sprache Java auch plattformunabhängig ist und damit dazu führt, dass alle Neuerungen auch zeitnah für Linux verfügbar sind, weckt große Hoffnungen und Erwartungen. Eine Liste mit sehr vielen Plug-ins finden Sie unter eclipse-plugins.2y.net. Stöbern Sie doch einfach mal und probieren Sie Verschiedenes aus. Sicher finden Sie dabei einige Werkzeuge, die Ihnen gute Dienste leisten können.