![]() |
10. GUI und Events
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Haben Sie's bermerkt? Bis jetzt konnte die Benutzerin Ihrer Applets nie eingreifen in das Geschehen im Applet. Das soll sich jetzt ändern! Damit Benutzer etwas
bewirken können,
muss das Applet Menüs, Tasten, Auswahllisten, Eingabefelder,
etc. haben. Das alles nennt man GUI (Graphical User Interface).
Sie haben schon mal ein User Interface gehabt, aber das war gar nicht "graphical" -
erinnern Sie sich an Console.class? Das war bisher die einzige Möglichkeit
für Eingaben in ein Programm. Wie damals versprochen soll das
jetzt komfortabler werden.
Die Methode add() ist eine Methode
einer
Superklasse von Applet und ermöglicht es, diesem ein grafisches Element
zuzufügen - hier eben die Taste. Die Methode paint(), die wir früher verwendet (überschrieben) haben, stammt nicht von Applet, sondern von einer ihrer Superklassen. Sie wird immer dann aufgerufen, wenn der Grafikbereich - in unserem Fall das Applet - neu dargestellt werden muss. Das braucht nicht nur der Start zu sein, es ist auch denkbar, dass das Applet verdeckt war und nun wieder sichtbar wird, dass die Benutzerin es vergrössert oder verkleinert und, für uns sehr wichtig: die Methode repaint() erzwingt, dass die Methode paint() aufgerufen wird. Dazu später mehr. Wieder ein Beispiel aus dem Alltag: Wenn es knallt, dann schaue ich herum um zu sehen, was passiert ist. Das Knallen ist ein Ereignis (= event), ich bin eine Instanz einer Klasse (das ist zwar etwas despektierlich, aber da ich mich selber als Beispiel nehme, werden Sie mich gewähren lassen). Ein Objekt kann also auf Events reagieren. Kann, denn wenn ich keine Ohren habe, dann geht's nicht. Wir müssen auch in Java "Ohren" machen, die Events wahrnehmen können. Sie heissen Listener. Es gibt verschiedenste Listener, so wie wir auch verschiedene Sinne haben, mit denen wir auf "Events" reagieren können. Listener sind wiederum Klassen (um genau zu sein: Es sind nicht Klassen, sondern Interfaces, aber dazu später mehr). Sie befinden sich im Package java.awt.event - also müssen wir dieses importieren. Die Standard - Listener tun nichts, also müssen wir von diesen eigene Klassen ableiten. Wir könnten also neben unserer Klasse Events eine Listener - Klasse erstellen, so wie Sie früher die Klasse MyColor erstellt haben, und dann davon eine Instanz machen. Das wäre aber wie mit Kanonen auf Spatzen geschossen: Wir brauchen diese kleine Listener - Klasse nur um den Event abzufangen. Seit dem JDK 1.1 gibt es innere Klassen (inner classes). Das sind Klassen, welche in eine andere Klasse verpackt sind. Und diese dürfen sogar anonym, also namenlos, sein. Genau solche anonymous classes verwendet man meist um Listener zu realisieren: sie werden direkt in den Methode verpackt, die einem GUI Element einen Listener zufügt. In unserem Falle heisst diese Methode addActionListener() und wir übergeben ihr unsere anonyme Klasseninstanz als Parameter in der runden Klammer:
Dieser ganze Quelltextausschnitt ist eigentlich nur der Aufruf der Methode addActionListener() ! Aber in der (runden) Parameter - Klammer, die in der ersten Zeile beginnt und in der letzten endet, geschieht einiges: mit "new" wird eine Instanz einer anonymen Klasse vom Typ ActionListener erzeugt, die dann auch gleich nach der ersten geschweiften Klammer ausprogrammiert wird. Sie überschreibt die Methode actionPerformed() der Klasse ActionListener. Diese wird aufgerufen, wenn der Event stattgefunden hat. Der Event selber ist wieder eine Klasse und heisst in unserem Falle ActionEvent. Sie wird der Methode als Parameter übergeben und wir könnten sie in der Methode weiter verwenden - dazu wieder mal später!
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Damit haben Sie eine GUI Komponente, den Button, etwas kennengelernt. Es gibt eine ganze Reihe weiterer Komponenten und auch Elemente, die Komponenten in sich aufnehmen und damit gruppieren können (Container). Es hat keinen Sinn, dass wir nun in aller Ausführlichkeit Element um Element besprechen. Die nachfolgende Tabelle soll Ihnen einen Überblick über die Möglichkeiten geben. Wenn Sie ein Element verwenden wollen, schreiben Sie den Klassennamen in den Editor, klicken Sie drauf, drücken Sie <F1> und Sie sehen alle Details zum Element. Am Ende des Kapitels schnuppern Sie dann noch etwas im GUI und den Events herum. Die GUI Elemente, welche hier vorgestellt werden, gehören übrigens zum "klassischen" Teil des JDK. Mit Java 2 wurde eine Oberflächengestaltung namens Swing geschaffen, die viel mehr Möglichkeiten bietet, entsprechend aber auch viel komplexer zu handhaben ist. Swing werden wir in einem speziellen Kapitel behandeln. Die GUI - Elemente auf einen Blick:
Und nun noch eine Spielerei mit Events. Bisher haben Sie ja nur den ActionEvent, der von einem Tastenklick produziert wird, kennengelernt. Der folgende Quelltext soll Sie in einen andern Event einführen. Er stellt das einfachste Zeichnungsprogramm aller Zeiten dar, der Embryo von Corel Draw sozusagen!
Schon im Header der Klasse Zeichnen gibt's was Neues: "implements MouseMotionListener". Ich habe schon gesagt, dass Listener keine Klassen sind, sondern Interfaces. Ein Interface ist fast wie eine Klasse, mit dem (grossen) Unterschied aber, dass man von ihm keine Instanzen machen und auch nicht mit "extends" Subklassen ableiten kann. Und doch kann man von einem Interface alle seine Eigenschaften erben, wenn man es implementiert (= implements). Man kann beliebig viele Interfaces implementieren und kann damit von vielen Interfaces erben. Damit ist die multiple inheritance, die es bei Java nicht gibt, doch durch ein Hintertürchen wieder da! Eine salomonische Lösung haben da die Entwickler von Java gefunden. Beim ActionEvent hätten wir das auch so machen können. Sie sehen hier eine zweite Art, wie man Listener verwenden kann. Da "Zeichnen" das Interface MouseMotionListener implementiert, kann sie all deren Methoden direkt verwenden. Und sie muss sogar all ihre Methoden überschreiben, auch wenn sie gar nicht gebraucht werden. Hier sind es zum Glück nur deren zwei: mouseMoved() wird aufgerufen, wenn die Maus bewegt wird und mouseDragged() wird aufgerufen, wenn die Maus bei gedrückter Taste bewegt wird. Es gibt übrigens auch den MouseListener, der reagiert, wenn eine Maustates gdrückt oder losgelassen wird, etc. Beachten Sie bitte, dass Sie alle Methoden dieser Listener überschreiben müssen, auch wenn Ihre Methode leer ist. Beim MouseListener sind dies die fünf Methoden mouseClicked(), mouseEntered(), mouseExited(), mousePressed() und mouseReleased().Sie schreiben also public void mouseClicked(MouseEvent e) { } und analog für alle andern Events, die nichts bewirken sollen. Vor der Methode addMouse... steht kein Name einer Klasseninstanz wie bei addActionListener. Wenn nichts vor einer Methode steht, dann wird die Methode aus der aktuellen Klasse aufgerufen, also Zeichnen: Also wird der MouseMotionListener dem Applet selber zugefügt. Sie könnten auch schreiben this.addMouse..., denn das Schlüsselwort this steht für die aktuelle Klasse. Es steht übrigens auch in der Parameterklammer. Hier muss es stehen und meint diesmal Zeichnen nicht als Applet, sondern als Listenerklasse. Da wir die Methode paint() des Applet nicht brauchen, müssen wir den Grafik - Kontext mit der Methode getGraphics() explizit verfügbar machen um dann darauf zeichnen zu können mit drawLine(). Und diesmal werten wir den Event auch aus: Er kann uns nämlich sagen, wo die Maus war, als sie "gedragged" wurde (schönes Deutsch, nicht wahr?): Die Methoden getX() und getY() des Events liefern uns diese Koordinate - und dahin zeichnen wir dann auch!
|
![]() |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Dieses Einfachst - Zeichnungsprogramm kann jetzt natürlich verbessert werden, solange, bis es ein ausgewachsenes Corel Draw ist. Meine Vorschläge für Ihre ersten Schirtte auf diesem weiten Weg:
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||