- Graphische Oberfläche
- Das Abstract Window Toolkit
- Swing vs AWT
- Erste Swing-Objekte
- extends JFrame
- implements ActionListener
- Der Konstruktor
super("TopDraw");
quit = new JButton("Verlassen");
quit.addActionListener(this);
getContentPane().add("South", quit);
- Die Methode
actionPerformed
- Plazierung (Layouts)
- Graphik-Ereignisse(Events)
- Das Aktion-Ereignisse(Action-Event)
- MouseListener
- Das TopDraw-Programm
- Erste Schritte
- Struktur
- Welches Element soll zum Zeichen benutzt werden?
- Die Zeichenlogik von
public void paint(Graphics g)
- Kann man paint vom Programm aus aufrufen?
- Das TopDraw - GUI
- Die Architektur des Objekts TopDraw v2
- Die Klasse Zeichenbar
- Die Klasse Strich
- Die Klasse Velleda
- Alles zusammen!
- Zusammenfassend
- Übung
Die Grundbibliotheken für java, liefern eine umfangreiche Menge an grafischen
Klassen. Diese können in der API
eingesehen werden, sowie im Swing-Tutorial.
Schaut man sich die Bibliothek genau an, wird festgestellt, dass viele Klasse
welche in AWT vorhanden sind, auch im swing-Teil erhältlich sind.
Dies ist eine historische hinterlassenschaft von vorherigen Versuchen und
Versionen von Sun's-JDK. Der erste Ansatz der verfolgt und in dem AWT
realisiert wurde bestand in der intensiven Nutzung von nativen
Funktionalitäten. Dies hatte zur folge, daß Applikaitonen auf verschiedenen
Systemen unterschiedlich aussahen. Weiterhin tauchten etliche Probleme auf, da
die verschiedenen graphischen Oberflächen (X-Windows, OpenView, MacOS, Windows)
verschiedene Fähigkeiten haben, und deshalb alle Implementationen sehr stark
auf die Zeilplatform ausgerichtet werden müssen.
Um dies zu umgehen wurde angefangen die AWT-Klassen auslaufen zu lassen (sie
werden zwar noch mitgeführt, aber nicht mehr weiterentwickelt) und eine neue
rein Java-Basierte graphische Bibliothek zu bauen.
Diese hat den Nachteil wesentlich Ressourcenhungriger als die AWT zu sein,
dafür ist aber sichergestellt, daß die Applikationen auf allen Plattformen dei
gleichen Ressourcen zur Verfügung bekommen und gleich aussehen.
Wir werden anch und nach ein kleines Vektororientiertes Zeichenprogramm
erzeugen. Als resten schritt werden wir ein Fenster öffenen und mit einem Knopf
zum Verlassen versehen.
Da wir ein Fenster öffnen wollen, müssen wir auch von dieser Klasse erben. Was
dort gemacht wird wird in unseren neuen Klasse spezifiziert.
Hiermit sagen wir, daß diese Klasse die Methode public void
actionPerformed(ActionEvent e)
implementiert. Diese Methode ist recht
speziell, sie führt gleich mehrere Konzepte ein:
Hauptsächlich im Graphikbereich werden die Interaktionen zwischen Elementen
über 'Events', Ereignissen gesteuert. Sobald der Benutzter z.B. auf einen Knopf
drückt wird so ein Ereignis ausgelöst.
Wir serden im Code später sehen, daß das Fenster als AktionListener dem
Knopf zugeordnet wird. Dank dieser Methode ist es möglich, daß ein und derselbe
AktionListener mehrere andere Bausteine 'überwacht' und dann reagiert wenn
diese eine Veränderung mitteilen (z.B. überwachen von einem Knopf, einem
Menüpunkt und einer Menutoolleiste).
In diesem Fall ist der Aktionlistener nicht separat definiert, sondern aus
einfachheit-halber als das JFrame definiert. In der Regel, werden für jeden
AktionsTypen eigene Listener definiert (was den Test ob das korrekte Element
das Ereignis ausgelöst hat, unnötig macht.
Der Konstruktor unsers Fensters ruft erst den
Konstruktorder Mutterklasse auf, welcher eine Zeichenkette bekommt (diese wird
als Fenstertitel eingesetzt).
Hier wird, ähnlich jedem anderen Objekt, ein Objekt der Klasse JButton
instanziiert, diesem JButton übergeben wir direkt einen statischen Text, der
auf dem Knopf angezeigt werden soll.
Damit wird dem Button mitgeteilt, daß das aktuelle Fenster die Instanz sein
wird welche eventuelle Aktions-Ereignisse des Knopfes verarbeiten wird.
Etwas umständlich anmutende Methode um dem Knopf in den südlichen Teil des
Fenster einzusetzen.
Wie vorher schon erwähnt wird diese Methode aufgerufen, wenn auf einem der
verfolgten Elemente ein Aktions-Event eintrifft. Der Parameter ist ein
aktionsEreignis. Wie aus dem folgenden Code ermittelt werden kann, wird aus
diesem Event der Erzeuger des Ereignisses ermittelt, und falls dieser unser
Verlassen-Knopf war, beenden wir unser Programm. Falls Die aktion von woanders
herkam, wird nichts gemacht.
Hier erzeugen wir ein Objekt der Klasse TopDrawWidow, und befehlen dem sich
sichtbar zu machen. Das Resultat sieht folgendermaßen aus:
Wir haben in dem vorangegangen Beispiel einen Knopf in ein Fenster eingefügt,
und damit nicht genug, wir wollten diesen Knopf in der südlichen Region.
Dies wird von java dadurch unterstützt, daß für graphische Objekte
sogenannnte Layout-Manager zur Verfügung stehen. Diese Layoutmanager haben
verschiedene Charakteristika. Der einfachst zu bedienende Layoutmanager,
welcher auch als Defaultlayoutmanager benutzt wird ist der BorderLayoutmanager.
Wie der Name schon suggeriert, ist dieses Layout Kantenorientiert, damit
besitzt ein BorderLayout 5 Felder: Nord, Süd, Ost, West und die Mitte
(North,South,East,West,Center).
Was die anderen Layoutmanager angeht, sollte das sehr gut gehaltene tutorial angeschaut werden, falls es weniger um die Theorie geht und
mehr um den Gebrauch, gibt es im Tutorial eine Zusammenfassung.
Wie schon weiter oben angedeuet, werden in grafischen Umgebungen die
Interaktionen zwischen Elementen über Ereignisse geregelt.
Auch hier hält das Tutorial eine sehr gute Beschreibung.
Das Paradigma, welches gewählt wurde, ist das jedes Element welches
Ereignisse auslösen kann, intern eine Liste mit den elementen hält welche sich
als Verarbeiter dieser Ereignisse bezüglich dieses einen Elements angemeldet
haben.
Dieses Ereignis, ist eines der Hauptbenutzten, da es alle Ereignisse abdeckt,
welche von Knöpfen und Menupunkten kommen.
Da wir zeichnen möchten, müssen wir die Bewegungen der Maus verfolgen, dazu ist
der MouseListener da, aus der API können die zu implementierenden Methoden extrahiert werden.
Nachdem noch ein paar Grundlagen eingebettet wurden, kommen wir zu unserem
Zeichenprogramm zurück:
Wir wollen jetzt dem Benutzer die Möglichkeit geben auf eine weiße Fläche zu
malen und diese auch wieder zu leeren.
Was wir baruchen ist eine große weiße Fläche in der Mitte, zum malen. Einen
Knopf zum löschen oben, einen Knof zum verlassen unten. Wenn der Benutzer die
Maus über der Fläche drückt, zieht und dann losläßt soll ein Strich zwischen
die zwei Punkt gezeichet werden.
Im AWT gab es das Objekt 'Canvas', in Swing gibt es kein solch für Graphik
spezialisiertes Element, wir werden den JComponent nehmen. Dazu werden wir eine
Klasse von JComponent erben lassen und die Methode paint redefinieren. Jedesmal
wenn das JComponent aufgefordert wird sich neu zu zeichnen wird die paint
Methode aufgerufen. Das System übergibt dieser Methode ein Objekt von Typ
Graphics, welches wir benutzen werden um unsere Graphischen Objekte zu
plazieren.
Die Zeichenbereiche besitzen keinen Puffer oder irgendwelche Art der
Errinnerung. Unser Objekt muß ishc las ganzes darstellen, jedesmal wenn es
durch paint, dazu aufgefordert wird. Dies ist sehr wichtig. Das ist der Grund
warum wenn eine Applikation oder ein Programm sich neu zeichnet, erst einaml
gelöscht werden muß.
Die Konsequenz, ist die, daß eine verzögerte Zeichenlogik aufgebaut werden
muß. Wir werden irgenwo alle Segmente, die der Benutzer gibt, speichern, damit
unere paint Methode diese Segmente finden und darstellen kann. Die Abbildung
wird also in zwei Schritten erfolgen:
- Alle Informationen bezüglich der zu zeichnenden Elemente speichern. Es gibt
also eine Tabelle mit den 4 charakteristischen Punkten.
- Die Methode paint redefinieren, die auf das Graphicobject alle
gespeicherten elemente zeichnet.
Nein, diese Methode wird auschließlich von System aufgerufen, allerdings gibt
es für den Benutzer die Methode repaint()
welche dem System
aufträgt zum nächsten möglichen Zeitpunkt dieses Objekt neu zu malen. Sonst
wird paint aufgerufen sobald est notwendig sein sollte (Fenster wurde verdeckt,
des-iconifiziert etc.)
Was das MainTopDraw angeht, braucht mans sich keine Gedanken zu machen: es
bleibt gleich.
Diese Klasse wurde als abstract
definiert, d.h. sie kann
nicht instanziiert werden. solche Klassen werden nur benutzt
um für andere Klassen eine gemeinsame Basis zu schaffen.
In unserem Beispiel wird die Klasse Strich
von dieser Klasse
erben, falls zu einem späteren Zeitpunkt Kreise, Elipsen, Schachteln etc
gezeichnet werden sollen, können diese auch von Zeichenbar abgeleitet werden
und generisch als Zeichenbar benutzt werden.
Die Klasse Strich beginnt mit einer komischen Deklaration: static Color farbe =
Color.blue. Was bedeutet dies, zur Errinnerung, statisch bedeutet für alle
Instanzen dierser Klasse gemeinsam. Weiterhin, der Konstruktor dieser Klasse
ist ziemlich einfach, er erlaubt es einfach per Kooridantenangabe das Objekt zu
instanziieren.
Das Objekt Graphics wird auf die gewünschte Farbe gesetzt, und das Segment
wird gezeichnet.
Objekte vom Typ Strich können sich demnach selber zeichnen, vorausgesetzt
man liefert ihnen ein Objekt vom Typ Graphics.
Neue Version von TopDrawWindow:
- Wie werden GUI-Ereignisse verteilt?
- Was macht die paint(Graphics)-Methode ?
- Wo wird eine Benutztschnittstelle aufgebaut, in welcher Klasse, welcher
Methode?
TopDraw so modifizieren, daß auch Kreise gezeichnet werden können. Hilfen: um
in eine Border-Zone (z.B. North) mehr als ein Element zu stecken, alle Elemente
in ein JPanel einfügen und dieses anbringen. Um das zu zeichnende Element
auszuwählen kann eine ComboBoxbenutzt werden. in der Klasse Math
befinden sich geläufige mathematische Funktionen.
Document mit wml erzeugt von Bruno Böttcher unter Benutzung von öffentlichen Dokumenten.