Swinging Java

Werbung
Kamper Andreas
Swinging Java
eine Fachbereichsarbeit aus Informatik
bei Prof. Mag. Peter Micheuz
BG und BRG Völkermarkt
Schuljahr 2001/2002
2
An
dieser
Stelle
möchte
ich
mich
recht
herzlich
bei
meinem
Informatikprofessor, Herrn Prof. Mag. Peter Micheuz, bedanken, der mich
während der Erstellung meiner Fachbereichsarbeit tatkräftig unterstützt hat.
3
Inhaltsverzeichnis
1. Einleitung ............................................................................................................................... 5
1.1. Vorwort ............................................................................................................................. 5
1.2. Was ist JAVA? ................................................................................................................. 6
1.3. Was ist SWING? ............................................................................................................. 6
1.4. Geschichte ........................................................................................................................ 7
1.4.1.
Entstehung und Entwicklung von JAVA ............................................................. 7
2. Einführung in Java und Objektorientierung
.................................................... 8
2.1. Grundlagen von JAVA ................................................................................................... 8
2.1.1.
2.1.2.
2.1.3.
2.1.4.
2.1.5.
Was ist das JDK? ................................................................................................. 8
Eigenschaften und Sprachmerkmale von JAVA ................................................. 9
Syntax ................................................................................................................ 10
Datentypen ......................................................................................................... 18
Ausdrücke .......................................................................................................... 20
2.2. Grundlagen der Objektorientierung ............................................................................ 21
2.2.1.
2.2.2.
2.2.3.
2.2.4.
2.2.5.
2.2.6.
2.2.7.
2.2.8.
2.2.9.
Klassen................................................................................................................
Objekte................................................................................................................
Methoden ............................................................................................................
Konstruktoren .....................................................................................................
Destruktoren........................................................................................................
Strukturierung ....................................................................................................
Vererbung ...........................................................................................................
Modifier (Lebensdauer, Sichtbarkeit, Veränderbarkeit) .....................................
Interfaces.............................................................................................................
22
22
23
23
25
25
27
29
31
3. SWING ................................................................................................................................. 33
3.1. Grundlagen .................................................................................................................... 33
3.1.1.
3.1.2.
3.1.3.
3.1.4.
3.1.5.
3.1.6.
3.1.7.
Abstract Windowing Toolkit .............................................................................
Vom AWT zum Swing ......................................................................................
Unterschiede AWT – Swing ...............................................................................
Vorteile / Nachteile von Swing ..........................................................................
Abhängigkeit Swing – AWT ..............................................................................
Eigenschaften von SWING ................................................................................
Swing – Package Überblick ...............................................................................
33
37
37
38
38
39
40
4
3.2. Container ....................................................................................................................... 42
3.2.1.
3.2.2.
3.2.3.
3.2.4.
3.2.5.
3.2.6.
JFrame ................................................................................................................
JRootPane ..........................................................................................................
JWindow ............................................................................................................
JDialog ................................................................................................................
JComponent .......................................................................................................
Weitere Container ..............................................................................................
42
44
46
46
48
48
3.3. Komponenten ................................................................................................................ 49
3.3.1.
3.3.2.
3.3.3.
3.3.4.
3.3.5.
3.3.6.
3.3.7.
Panels .................................................................................................................. 51
Label und Textfelder .......................................................................................... 51
Buttons ............................................................................................................... 52
Listen / Comboboxen ......................................................................................... 52
Schieberegler ...................................................................................................... 53
Menüs ................................................................................................................. 54
Weitere Komponenten ....................................................................................... 55
3.4. Look and Feel ................................................................................................................ 56
3.5. Model – View – Controller ........................................................................................... 58
3.6. Layout-Manager ............................................................................................................ 59
3.7. Event – Handling ........................................................................................................... 62
4. Beispielprogramme ........................................................................................................ 64
4.1. Millionenshow ................................................................................................................ 64
4.2. Browser .......................................................................................................................... 75
4.3. Lotto ............................................................................................................................... 80
5. Entwicklersoftware ........................................................................................................ 92
5.1. JBuilder .......................................................................................................................... 92
5.2. Forte4Java ..................................................................................................................... 94
5.3. JavaEditor ...................................................................................................................... 95
6. Literaturverzeichnis ...................................................................................................... 96
5
1. Einleitung
1.1 Vorwort
Eigentlich hatte ich nie geplant eine Fachbereichsarbeit zu schreiben. Erst Anfang dieses
Schuljahres
kam
ich,
natürlich
nicht
zuletzt
wegen
der
Anregungen
meines
Informatikprofessors, auf diese Idee.
Professor Peter Micheuz schlug mir vor, über das Thema „Swinging Java“ zu schreiben. Mich
persönlich interessiert diese Programmiersprache sehr und ich war von Anfang an begeistert.
Höchstwahrscheinlich hätte ich mich sowieso in meiner Freizeit mit Java beschäftigt, also
dachte ich mir, ich könnte doch gleich eine Fachbereichsarbeit schreiben.
Zu Beginn hatte ich noch einige Bedenken, weil ich zuvor eigentlich noch keinerlei Java Kenntnisse hatte. Doch mit Hilfe guter Lernunterlagen konnte ich mich recht gut einarbeiten.
Die Matura rückt immer näher und es ist viel zu tun. Die Weihnachtsferien und ein Großteil
meiner Freizeit wurde genützt um an der Fachbereichsarbeit weiterzuarbeiten.
Aber eines ist klar: Der Aufwand hat sich vollkommen gelohnt. Mit der Unterstützung meines
Informatikprofessors konnte ich schließlich die Fachbereichsarbeit so umsetzen, wie ich sie
geplant hatte.
6
1.2 Was ist JAVA?
Java ist sowohl eine objektorientierte Programmiersprache in der Tradition von Smalltalk als
auch eine klassische imperative Programmiersprache nach dem Vorbild von C.
Mit einer großen Anzahl von anspruchsvollen Features wie Multithreading, strukturiertem
Exceptionhandling oder eingebauten grafischen Fähigkeiten verfügt Java über eine Reihe
interessanter Neuerungen auf dem Gebiet der Programmiersprachen.
Um einem Missverständnis vorzubeugen:
JavaScript ist nicht Java!
JavaScript ist eine Skript-Sprache, die in HTML eingebettet werden kann und bei manchen
Web-Browsern (Netscape, Internet-Explorer) die Ausführung von bestimmten Funktionen
und Aktionen innerhalb des Web-Browsers bewirkt.
Im Gegensatz zu Java ist JavaScript
!
keine selbstständige Programmiersprache,
!
nicht von der Browser-Version unabhängig,
!
nicht mit den notwendigen Sicherheitsmechanismen ausgestattet.
1.3 Was ist SWING?
Die Java Foundation Classes (JFC) Software erweitert das Abstract Windowing Toolkit
(AWT: siehe Seite 33) mit einem umfassenden Satz von graphischen Bibliotheken.
Swing ist ein Graphical User Interface (GUI) Komponenten Werkzeug, Teil der Java
Foundation Classes (JFC), einbezogen in die Java 2 Plattform. Swing erleichtert das Einsetzen
von Anwendungen mittels Bereitstellen eines gänzlich in Java geschriebenen Satzes von
UserInterface Elementen. Swing Komponenten gestatten ein benutzerdefiniertes „Look and
Feel“ ohne von einem konkreten „windowing system“ abhängig zu sein.
Da Swing in der Java 2 Plattform enthalten ist, muss man es nicht downloaden oder
installieren.
7
1.4 Geschichte
1.4.1 Entstehung und Entwicklung von JAVA
Alles fing mit einer Mail des damals 25-jährigen Programmierers Patrick Naughton an den
SUN-Chef Scott McNealy an. Naughton hatte angekündigt, das Unternehmen zu verlassen,
um zu Next Computer, Inc. zu wechseln. Er war der Meinung, dass bei SUN einige sehr
grundsätzliche Dinge nicht gut liefen. McNealy forderte ihn daraufhin auf, seine Kritik mit
eventuellen Lösungsvorstellungen niederzuschreiben.
Im Großen und Ganzen warf er SUN vor, auf dem besten Wege zu sein, sich mehr und mehr
von seinen potentiellen Kunden und Anwendern zu entfernen. Er forderte Hard- und
Software, die nicht nur von Akademikern und hochspezialisierten Profis, sondern von
normalen Menschen angewendet werden konnte.
Im Jahre 1991 arbeitete ein kleines Team unter der Leitung von James Gosling an einem
Projekt, dessen Ziel es war, eine neue Programmiersprache zu entwickeln, die sich in
besonderer Weise zur Programmierung von elektronischen Geräten der Konsumgüterindustrie
eignen sollte - also zum Programmieren von Toastern, Kaffeemaschinen, Videogeräten,
Decodern für Fernsehgeräte usw. Leider blieb der erhoffte Erfolg aus.
1993 wurde die Zielrichtung des Projekts geändert. Der Arbeitstitel des ursprünglichen
Projektes “OAK” (Objekt Application Kernel wurde in “Java” umbenannt, was im
Amerikanischen ein Synonym für guten Bohnenkaffee ist. Die neue Zielsetzung war
folgende: eine Programmiersprache zu entwickeln, die sich in besonderer Weise zur
Programmierung auf verschiedenen Rechnertypen im Internet eignen sollte.
Seit 1995 bietet SUN den Kern eines Javaprogrammiersystems JDK (Java Development Kit)
zusammen mit einer Implementierung des Java-Interpreters (Java Virtual Machine) kostenlos
an. Die meisten kommerziellen Programmierumgebungen für Java nutzen das JDK als
Kernsystem.
Im Jahre 1995 wurde Java der Öffentlichkeit vorgestellt. Seitdem hat sich diese
Programmiersprache schneller verbreitet als jede andere neue Programmiersprache der letzten
Jahre.
[Quelle: Guido Krüger: GoTo Java 2 und Heinz-Peter Gumm / Manfred Sommer: Einführung in die Informatik]
8
2. Einführung in Java und Objektorientierung
2.1 Grundlagen von Java
2.1.1 Was ist das JDK?
Das Java Development Kit (JDK) umfasst die für die Erstellung und das Testen von JavaApplikationen und Applets notwendige Software, die Packages mit den zur Grundausstattung
gehörenden Java-Klassen, und die Online-Dokumentation.
Zur Software gehören der Java-Compiler, das Java Runtime Environment (die Java Virtual
Machine) für die Ausführung von Applikationen, der Appletviewer für die Ausführung von
Applets, ein Java-Debugger und verschiedene Hilfsprogramme.
Die Online-Dokumentation umfasst eine Beschreibung aller Sprachelemente und aller
Klassen des Application Program Interface API.
Java ist eine relativ junge Programmiersprache und daher noch immer in Entwicklung, d.h. es
kommen immer wieder neue Versionen mit Ergänzungen und Verbesserungen heraus:
!
Die Urversion ist JDK 1.0 (1995).
!
Im Jahr 1997 kam Version 1.1 heraus, das brachte sowohl Änderungen und neue
Konzepte (bei den Methodennamen gemäß den Beans-Konventionen, beim EventHandling, bei den Text-Files) als auch Erweiterungen durch zusätzliche Packages
(z.B. für Datenbanken).
!
Ende 1998 kam Version 1.2 mit umfangreichen Erweiterungen (unter anderem
Swing).
!
Anfang 2000 folgte Version 1.3 mit Fehlerkorrekturen und PerformanceVerbesserungen.
Seit Version 1.2 wird das JDK auch „Java-Plattform 2“ genannt # „Java 2 Software
Development Kit (SDK)“
Das JDK erhält man kostenlos (z.B. zum Download über das Internet).
[Quelle: Guido Krüger: GoTo Java 2 und Heinz-Peter Gumm / Manfred Sommer: Einführung in die Informatik]
9
2.1.2 Eigenschaften und Sprachmerkmale von JAVA
Java wurde vollständig neu entworfen. Die Designer versuchten, die Syntax der Sprachen C
und C++ soweit wie möglich nachzuahmen, verzichteten aber auf einen Großteil der
komplexen und fehlerträchtigen Merkmale beider Sprachen. Das Ergebnis ihrer Bemühungen
haben sie wie folgt zusammengefasst:
»Java soll eine einfache, objektorientierte, verteilte, interpretierte, robuste, sichere,
architekturneutrale, portable, performante, nebenläufige, dynamische Programmiersprache
sein.«
Javaprogramme sind portabel, sie können also ohne jede Änderung auf unterschiedlichen
Rechnern eingesetzt werden. Dies ist eine Voraussetzung für die Integration von JavaAnwendungen, so genannten Applets, in Internet-Seiten. Für diesen Zweck besitzt Java
spezielle Sicherheitsmechanismen.
Javaprogramme sind für unterschiedliche Anwendungszwecke geeignet. Man kann kurze
Testprogramme schreiben, die in einem einfachen Fenster ablaufen, aber auch komplette
Anwendungen, so wie sie für heutige Grafikoberflächen typisch sind.
Dort wo Software kommerziell entwickelt wird, hat Java rasch Fuß gefasst, weil es ein
modernisiertes C++ ist. Diese Sprache hatte sich in den letzten Jahren zum Industriestandard
entwickelt, daher fällt eine Umstellung auf Java nicht schwer.
Im Allgemeinen ist Java eine sehr übersichtliche Sprache:
In Java gibt es die meisten elementaren Datentypen, die auch C besitzt. Arrays und Strings
sind als Objekte implementiert und sowohl im Compiler als auch im Laufzeitsystem
verankert. Alle primitiven Datentypen sind vorzeichenbehaftet und in ihrer Größe exakt
spezifiziert.
Die
Ausdrücke
in
Java
entsprechen
weitgehend
denen
von
C
und
C++.
Variablendeklarationen werden wie in C++ als Anweisungen angesehen und können an
beliebiger Stelle innerhalb des Code-Parts eines Programms auftauchen
Als OOP-Sprache besitzt Java alle Eigenschaften moderner objektorientierter Sprachen. Wie
C++ erlaubt Java die Definition von Klassen, aus denen Objekte erzeugt werden können.
Objekte werden dabei als Referenzdatentypen behandelt, die wie Variablen angelegt und
verwendet werden können.
10
Das Speichermanagement in Java erfolgt automatisch. Ein Garbage-Collector, der als
niedrigpriorisierter Hintergrundprozess läuft, sucht in regelmäßigen Abständen nach nicht
mehr referenzierten Objekten und gibt den durch sie belegten Speicher an das Laufzeitsystem
zurück.
[Quelle: Guido Krüger: GoTo Java 2 und Heinz-Peter Gumm / Manfred Sommer: Einführung in die Informatik]
2.1.3 Syntaxgrundlagen
Einfaches Programm
public class Klassenname
{ public static void main (String[] args)
{ Anweisung1;
Anweisung2;
...
}
}
Beispiel:
public class Hallo
{ public static void main (String[] args)
{ System.out.print("Hallo ");
}
}
Anweisungen:
Block – Anweisung
{
Anweisung1;
Anweisung2;
...
}
Beispiel:
{ double neuerKontostand = kontostand - betrag;
kontostand = neuerKontostand;
}
11
Ein Block ist eine Zusammenfassung von Anweisungen, die nacheinander ausgeführt werden.
Im Block gelten die Anweisungen als eine Einheit. Somit kann der Block auch
Variablendeklarationen enthalten, wie z.B. lokale Variablen, die nur in diesem Block sichtbar
sind.
Die if-Anweisung
if (Bedingung)
Anweisung
oder:
if (Bedingung)
anweisung1
else
anweisung2
Beispiel:
if (betrag <= kontostand)
kontostand = kontostand - betrag;
Die if-Anweisung wertet zunächst den Ausdruck aus. Die Anweisung wird nur dann
ausgeführt, wenn das Ergebnis des Ausdrucks true ist. Andernfalls wird mit der ersten
Anweisung nach der if-Anweisung fortgefahren.
Mit der if-else-Anweisung gibt es eine weitere Verzweigung in Java. Falls der Ausdruck wahr
ist, wird anweisung1 ausgeführt, andernfalls anweisung2. Eine der beiden Anweisungen wird
also in jedem Fall ausgeführt.
Switch - Anweisung
switch (ausdruck)
{
case constant:
anweisung;
...
default:
}
Die switch-Anweisung ist eine Mehrfachverzweigung. Zunächst wird der Ausdruck ausdruck,
der vom Typ byte, short, char oder int sein muss, ausgewertet. In Abhängigkeit vom Ergebnis
12
wird dann die Sprungmarke angesprungen, deren Konstante mit dem Ergebnis des Ausdrucks
übereinstimmt. Die Konstante und der Ausdruck müssen dabei zuweisungskompatibel sein.
Schleifen:
Die while-Schleife
while (Bedingung)
Anweisung
Beispiel:
while (kontostand < 2 * anfangsstand)
{ jahr++;
double zinsen = kontostand * zinssatz / 100;
kontostand = kontostand + zinsen;
}
Zuerst wird der Testausdruck, der vom Typ boolean sein muss, geprüft. Ist er true, wird die
Anweisung ausgeführt, andernfalls wird mit der ersten Anweisung hinter der Schleife
weitergemacht. Nachdem die Anweisung ausgeführt wurde, wird der Testausdruck erneut
geprüft usw. Die Schleife wird beendet, sobald der Test false ergibt.
do –Schleife
do
anweisung;
while (ausdruck);
Die do-Schleife wird mindestens einmal ausgeführt, weil der Ausdruck erst danach überprüft
wird. Ergibt der Ausdruck false, wird sie beendet.
Die for- Schleife
for (Initialisierung;Bedingung;Aktualisierung)
{ Anweisung
}
13
Beispiel:
for ( i = 1; i <= 20; i++ )
{ double zinsen = kontostand * zinssatz / 100;
kontostand = kontostand + zinsen;
}
Ablauf der Schleife: Ausführung einer Initialisierung; anschließend wiederholte Ausführung
einer Anweisung und Aktualisierung eines Ausdrucks solange eine Bedingung wahr ist.
!
Der init-Ausdruck dient dazu, Initialisierungen durchzuführen, die durch die
Auswertung von Ausdrücken mit Nebeneffekten verursacht werden. Der
Rückgabewert der Ausdrücke wird vollständig ignoriert.
Der init-Teil darf auch aus mehreren Ausdrücken bestehen, wenn die einzelnen
Teilausdrücke durch Kommata getrennt sind. Um einen Schleifenzähler zu erzeugen,
muss der init-Teil eine Variablendeklaration enthalten.
!
Der test-Teil wird, ähnlich wie bei der while-Schleife, am Anfang der Schleife
ausgeführt, und die Schleifenanweisung wird nur ausgeführt, wenn die Auswertung
des Testausdrucks true ergibt.
!
Der update-Ausdruck dient dazu, den Schleifenzähler zu verändern. Er wird nach
jedem Durchlauf der Schleife ausgewertet, bevor der Testausdruck das nächste Mal
ausgewertet wird.
Methoden-Aufruf
objekt.methodenName(parameter)
Beispiel:
System.out.println("Hallo!");
Die Ausführung einer Methode (eines Objekts oder einer Klasse) wird veranlasst und die
notwendigen Parameter zur Verfügung gestellt.
14
Objekt-Erzeugung
new Klassenname ( parameter )
Beispiel:
new Rectangele(5, 10, 20, 30);
new Auto("Honda",1985);
Ein neues Objekt wird erzeugt und mit den Konstruktions-Parametern initialisiert.
Der Konstruktor gibt eine Referenz (einen Verweis, einen Zeiger) auf das konstruierte Objekt
zurück.
Import einer Klasse
import packageName.KlassenName;
Beispiel:
import java.awt.Rectangle;
Eine Klasse wird aus einem Package importiert.
Variablen-Deklaration
TypName variabenName;
oder
TypName variablenName = ausdruck;
Beispiele:
int summe;
int wert = 8;
Mit dieser Anweisung erfolgt die Festlegung einer neuen Variablen eines bestimmten Typs
und – wenn erwünscht – auch die Zuweisung eines Anfangswerts („Initialisierung“).
15
Wertzuweisung
variablenName = ausdruck;
Beispiel:
summe = summe + 25;
Einer Variablen wird ein neuer Wert zugewiesen.
Typ-Umwandlung( 'cast' ):
(TypName) ausdruck;
Beispiele:
(int)(x+0.5);
(int)Math.round(100 * f);
Es erfolgt eine Typumwandlung eines Ausdrucks (unter Informationsverlust).
Aufruf statischer Methoden
KlassenName.methodenName(parameter)
Beispiel:
Math.round(3.14);
Statische Methoden (Methoden, die nicht auf einem Objekt operieren) werden aufgerufen
und passende Parameter werden eingesetzt.
Konstanten-Deklaration
final TypName variablenName = ausdruck;
final TypName variablenName;
16
Beispiel:
final double DOSEN_INHALT = 0.355;
Eine Konstante eines bestimmten Typs wird definiert. Diese muss zwar nicht gleich
initialisiert werden, aber man kann Konstanten nur einmal einen Wert zuweisen.
Methoden Implementation
public class KlassenName
{ ...
zugriffsSpezifizierer rückgabeTyp methodenName(parameterTyp parameterName, ...)
{ Implementation
}
}
Beispiel:
public class BankKonto
{ ...
public void einzahlen(double betrag)
{ kontoStand = kontoStand + betrag;
}
...
}
Die Arbeitsweise einer Methode wird definiert.
Daten-Feld Deklaration (Instanz-Variable)
class KlassenName
{ ...
ZugriffsSpezifizierer Typ Variablenname ;
}
Beispiel:
public class BankKonto
{ ...
private double kontostand;
}
Eine Variable, die in jedem Objekt einer Klasse vorhanden ist, wird deklariert.
17
Die return - Anweisung
return ausdruck;
oder
return;
Beispiel:
public class BankKonto
{ public double getKontoStand()
{ return kontostand;
}
...
}
Bewirkt das Beenden der Methode und die Rückgabe des Ausdrucks; d. h. der return-Wert
wird der Wert des Methodenaufrufs im aufrufenden Programm.
Konstruktor - Implementation
class KlassenName
{ ...
ZugriffsSpezifizierer KlassenName (parameterTyp parameterName, ... )
{ .. Implementation des Konstruktors
}
}
Beispiel:
public class BankKonto
{ ...
public BankKonto(double eroeffnungsKontostand)
{ kontostand = eroeffnungsKontostand;
}
...
}
Das Verhalten eines Konstruktors wird festlegt. Konstruktoren werden gebraucht um neu
erzeugte Objekte zu initialisieren.
[Quelle: http://ada.rg16.asn-wien.ac.at/~javafs/indexjfs.html]
18
2.1.4 Datentypen
Eingabezeichen:
Java legt den neueren Zeichensatz Unicode zugrunde, der praktisch alle weltweit geläufigen
Zeichensätze vereint. Ein Unicode-Zeichen ist 2 Byte, also 16 Bit, lang. Der Unicode ist mit
den ersten 128 Zeichen des ASCII- und mit den ersten 256 Zeichen des ISO-8859-1Zeichensatzes kompatibel.
Kommentare:
In Java gibt es 3 Arten von Kommentaren:
! Einzeilige Kommentare beginnen mit // und enden am Ende der aktuellen Zeile.
! Mehrzeilige Kommentare beginnen mit /* und enden mit */.
Sie können sich über mehrere Zeilen erstrecken.
! Dokumentationskommentare beginnen mit /** und enden mit */.
Sie können sich ebenfalls über mehrere Zeilen erstrecken.
Kommentare derselben Art sind nicht schachtelbar. Ein Java-Compiler akzeptiert aber einen
einzeiligen innerhalb eines mehrzeiligen Kommentars und umgekehrt.
Dokumentationskommentare dienen dazu, Programme im Quelltext zu dokumentieren. Mit
Hilfe des Tools „javadoc“ werden sie aus der Quelle extrahiert und in ein HTML-Dokument
umgewandelt
Primitive Datentypen:
Alle primitiven Datentypen in Java haben eine feste Länge, die von den Designern der
Sprache ein für allemal verbindlich festgelegt wurde. Ein sizeof-Operator, wie er in C
vorhanden ist, wird in Java daher nicht benötigt und ist auch nicht vorhanden.
Typname
Länge
Wertebereich
Standardwert
boolean
1
true, false
false
char
2
Alle Unicode-Zeichen
\u0000
byte
1
-27...27-1
0
short
2
-215...215-1
0
int
4
-231...231-1
0
long
8
-263...263-1
0
float
4
+/-3.40282347 * 1038
0.0
double
8
+/-1.79769313486231570* 10308
0.0
[Quelle: Guido Krüger: GoTo Java 2]
19
Java kennt die beiden IEEE-754-Fließkommatypen float (einfache Genauigkeit) und double
(doppelte Genauigkeit). Die Länge beträgt 4 Byte für float und 8 Byte für double.
Variablen:
Variablen dienen dazu, Daten im Hauptspeicher eines Programms abzulegen und
gegebenenfalls zu lesen oder zu verändern. In Java gibt es drei Typen von Variablen:
!
Instanzvariablen, die im Rahmen einer Klassendefinition definiert und zusammen mit
dem Objekt angelegt werden.
!
Klassenvariablen, die ebenfalls im Rahmen einer Klassendefinition definiert werden,
aber unabhängig von einem konkreten Objekt existieren.
!
Lokale Variablen, die innerhalb einer Methode oder eines Blocks definiert werden und
nur dort existieren.
Eine Variable in Java ist immer typisiert. Sie ist entweder von einem primitiven Typ oder von
einem Referenztyp. Mit Ausnahme eines Spezialfalls bei Array-Variablen, auf den wir später
zurückkommen, werden alle Typüberprüfungen zur Compile-Zeit vorgenommen. Java ist
damit im klassischen Sinne eine typsichere Sprache.
Variablen können auf zwei unterschiedliche Arten verändert werden:
!
durch eine Zuweisung
!
durch einen Inkrement- oder Dekrement-Operator
Arrays:
Arrays in Java unterscheiden sich dadurch von Arrays in anderen Programmiersprachen, dass
sie Objekte sind. Obwohl dieser Umstand in vielen Fällen vernachlässigt werden kann,
bedeutet er dennoch:
!
dass Array-Variablen Referenzen sind
!
dass Arrays Methoden und Instanz-Variablen besitzen
!
dass Arrays zur Laufzeit erzeugt werden
20
Dennoch bleibt ein Array immer eine (möglicherweise mehrdimensionale) Reihung von
Elementen eines festen Grundtyps. Arrays in Java sind semidynamisch, d.h. ihre Größe kann
zur Laufzeit festgelegt, später aber nicht mehr verändert werden
Die Deklaration eines Arrays in Java erfolgt in zwei Schritten:
!
Deklaration einer Array-Variablen
!
Erzeugen eines Arrays und Zuweisung an die Array-Variable
Die Deklaration eines Arrays entspricht syntaktisch der einer einfachen Variablen, mit dem
Unterschied, dass an den Typnamen eckige Klammern angehängt werden:
Beispiel:
int[] a; double[] b; boolean[] c;
2.1.5 Ausdrücke
Wie in den meisten anderen Programmiersprachen gehören auch in Java Ausdrücke zu den
kleinsten ausführbaren Einheiten eines Programms. Sie dienen dazu, Variablen einen Wert
zuzuweisen, numerische Berechnungen durchzuführen oder logische Bedingungen zu
formulieren.
Ein Ausdruck besteht immer aus mindestens einem Operator und einem oder mehreren
Operanden, auf die der Operator angewendet wird. Nach den Typen der Operanden
unterscheidet man numerische, relationale, logische, bitweise, Zuweisungs- und sonstige
Operatoren. Jeder Ausdruck hat einen Rückgabewert, der durch die Anwendung des
Operators auf die Operanden entsteht. Der Typ des Rückgabewerts bestimmt sich aus den
Typen der Operanden und der Art des verwendeten Operators.
21
2.2 Grundlagen der Objektorientierung
Programmsysteme kann man auf zweierlei Weise strukturieren:
1. Durch eine funktionale Abstraktion:
d. h. in dem das gesamte Programm als ein großer Algorithmus aufgefasst wird, der
durch Verfeinerung der Algorithmen bis auf elementare Anweisungen zerlegt wird.
Prozeduren werden in Unterprozeduren mit Unterprozeduren (usw.) zerlegt. Daten und
Algorithmen werden getrennt behandelt. Bei größeren Programmsystemen führt diese
Art aber zu erheblichen Problemen.
2. Durch Datenabstraktion:
d. h. die Datenstrukturen stehen im Mittelpunkt der Betrachtung und sie haben eigene
Algorithmen zur Verfügung, die sie zur Erledigung ihrer Aufgaben und Änderung
ihres Zustands benötigen. Diese Sichtweise ist Grundlage der objektorientierten
Programmierung(OOP).
Der entscheidende Unterschied liegt darin, dass bei OOP die Objekte sozusagen „ein
Gedächtnis“ haben, also immer den Zustand ihrer Daten kennen.
Die grundlegenden Prinzipien von OOP sind Abstraktion, Kapselung, Modularisierung und
Hierarchie. Nicht Prozeduren und Funktionen wie bei der ablauforientierten strukturierten
Programmierung bilden das Gerüst des Systems, sondern Objekte und Objekttypen (Klassen),
die Eigenschaften und eigene Operationen (Methoden) besitzen. Ein Programmsystem kann
damit aus Objekten zusammengebaut werden, die miteinander in Verbindung stehen und sich
gegenseitig Aufträge zusenden. Jedes Objekt erledigt damit einen und nur den Teil der
Aufgaben, für den es verantwortlich ist. Das Zusammenwirken aller beteiligten Objekte löst
die Gesamtaufgabe.
[Quelle: http://www.oszhdl.be.schule.de/gymnasium/faecher/informatik]
22
2.2.1 Klassen
Eine Klassendefinition in Java wird durch das Schlüsselwort class eingeleitet. Anschließend
folgt innerhalb von geschweiften Klammern eine beliebige Anzahl an Variablen- und
Methodendefinitionen.
public class Tier
{
public String art;
public int geburtsjahr;
public int gewicht;
}
Diese Klasse ist methodenlos. Sie enthält lediglich die Variablen art, geburtsjahr und
gewicht. Diese Variablen werden meist als Membervariablen bezeichnet.
2.2.2 Objekte
Um von einer Klasse ein Objekt anzulegen, muss eine Variable vom Typ der Klasse deklariert
und ihr mit Hilfe des new-Operators ein neu erzeugtes Objekt zugewiesen werden:
Tier saeugetier;
saeugetier = new Tier ();
Die erste Anweisung ist eine normale Variablendeklaration. Die zweite Anweisung generiert
mit Hilfe des new-Operators eine neue Instanz der Klasse Tier und weist sie der Variablen
saeugetier zu.
In Java wird jede selbst definierte Klasse mit Hilfe des new-Operators instanziert.
Die beiden Anweisungen kann man auch kombinieren:
Tier saeugetier = new Tier ();
Zunächst haben alle Variablen Standardwerte. So kann man den Variablen Werte zuweisen:
saeugetier.name = "Katze";
saeugetier. geburtsjahr = 1992;
saeugetier. gewicht = 4;
23
2.2.3 Methoden
Methoden
definieren
das
Verhalten
von
Objekten.
Sie
werden innerhalb einer
Klassendefinition angelegt und haben Zugriff auf alle Variablen des Objekts. Methoden
ähneln den Funktionen anderer Programmiersprachen, jedoch arbeiten sie immer mit den
Variablen des aktuellen Objekts.
Wir berechnen das Alter dieses Tieres:
public class Tier
{
public String name;
public int geburtsjahr;
public int gewicht;
public int alter()
{
return 2002 - geburtsjahr;
}
}
Der Aufruf einer Methode (in diesem Fall der Methode alter) könnte so erfolgen:
Tier saeugetier= new Tier ();
saeugetier. geburtsjahr = 1992;
System.out.println(saeugetier.alter());
Das Programm würde „10“ auf dem Bildschirm ausgeben.
2.2.4 Konstruktoren
In jeder objektorientierten Programmiersprache lassen sich spezielle Methoden definieren, die
bei der Initialisierung eines Objekts aufgerufen werden: die Konstruktoren.
In Java werden Konstruktoren als Methoden ohne Rückgabewert definiert, die den Namen der
Klasse erhalten, zu der sie gehören. Konstruktoren dürfen eine beliebige Anzahl an
Parametern haben und können überladen werden.
24
Als Beispiel erweitern wir die Klasse Tier um einen Konstruktor:
public class Tier
{
public String name;
public int geburtsjahr;
public int gewicht;
public Tier (String name)
{
this. name = name;
}
}
Bei this handelt es sich um einen Zeiger, der beim Anlegen eines Objekts automatisch
generiert wird. this ist eine Referenzvariable, die auf das aktuelle Objekt zeigt und dazu
verwendet wird, die eigenen Methoden und Instanzvariablen anzusprechen. Der this-Zeiger ist
auch explizit verfügbar und kann wie eine ganz normale Objektvariable verwendet werden.
Wenn wir jetzt ein Objekt instanzieren wollen, müssen wir die Argumente wie bei einem
Methodenaufruf in Klammern nach dem Namen des Konstruktors angeben:
Tier saeugetier = new Tier ("Katze");
System.out.println(saeugetier.name);
In diesem Fall wird zunächst Speicher für das Tier-Objekt beschafft und dann der Konstruktor
aufgerufen. Dieser initialisiert seinerseits die Instanzvariable name mit dem übergebenen
Argument „Katze“. Der nachfolgende Aufruf gibt dann diesen Text am Bildschirm aus.
Unterschiedliche Konstruktoren können in Java auch problemlos verkettet werden. Das hat
den Vorteil, dass der vorhandene Code wieder verwendet wird. Der aufzurufende Konstruktor
wird dabei als eine normale Methode angesehen, die über den Namen „this“ aufgerufen
werden kann.
public Tier (String name,
int geburtsjahr,
int gewicht)
{
this(name);
this. geburtsjahr = geburtsjahr;
this. gewicht = gewicht;
}
25
Beim Instanzieren eines neuen Objekts werden die Initialisierungschritte in einer genau
festgelegten Reihenfolge ausgeführt:
!
Zunächst werden die Superklassenkonstruktoren aufgerufen.
!
Anschließend werden alle Membervariablen in der Reihenfolge ihrer Deklaration
initialisiert.
!
Schließlich wird der Programmcode im Rumpf des Konstruktors ausgeführt.
2.2.5 Destruktoren
Neben Konstruktoren, die während der Initialisierung eines Objekts aufgerufen werden, gibt
es in Java auch Destruktoren. Sie werden unmittelbar vor dem Zerstören eines Objekts
aufgerufen.
Ein Destruktor wird als geschützte (protected) parameterlose Methode mit dem Namen
finalize definiert:
protected void finalize()
{
...
}
Destruktoren sind aber nicht so bedeutend wie in anderen objektorientierten Sprachen. Der
Grund dafür ist, dass Java über ein automatisches Speichermanagement verfügt Anders als
etwa in C++ muss man sich nicht um die Rückgabe von belegtem Speicher kümmern.
2.2.6 Strukturierung
In großen Programmsystemen reichen Klassen als Strukturelemente alleine nicht aus. Aus
diesem Grund bietet Java mit den Packages (Paketen) eine weitere Kollektion für
Programmelemente an.
Ein Paket ist eine Sammlung von Klassen, jede Klasse in Java ist Bestandteil eines Pakets.
Paketnamen können aus mehreren Teilen bestehen und beliebig tiefe Hierarchien ausdrücken.
26
Der Name einer Methode oder einer Variablen besteht damit grundsätzlich aus drei
Elementen:
!
Paketname
!
Klassen- oder Objektname
!
Methoden- bzw. Variablenname
Damit eine Klasse verwendet werden kann, muss angegeben werden, in welchem Paket sie
liegt. Hierzu gibt es zwei unterschiedliche Möglichkeiten:
1.) Die Klasse wird über ihren vollen Namen angesprochen:
java.util.Date d = new java.util.Date();
2.) Am Anfang des Programms werden die gewünschten Klassen mit Hilfe einer importAnweisung eingebunden:
import java.util.*;
...
Date d = new Date();
Die Verwendung voll qualifizierter Namen hat den Nachteil, dass die Klassennamen sehr lang
und unhandlich werden. Bequemer ist daher die Anwendung der zweiten Variante, bei der die
benötigten Klassen mit Hilfe einer import-Anweisung dem Compiler bekannt gemacht
werden.
Die import-Anweisung gibt es ebenfalls in zwei unterschiedlichen Ausprägungen:
1.) Mit der Syntax import Paket.Klasse; wird genau eine Klasse importiert. Alle anderen
Klassen des Pakets bleiben unsichtbar:
import java.util.Date;
...
Date d = new Date();
java.util.Vector = new java.util.Vector();
27
2.) Unter Verwendung der Syntax import Paket.*; können alle Klassen des angegebenen
Pakets auf einmal importiert werden:
import java.util.*;
...
Date d = new Date();
Vector v = new Vector();
2.2.7 Vererbung
Neben der Möglichkeit, Variablen und Methoden zu Klassen zusammenzufassen, ist die
Vererbung, also die Möglichkeit, Eigenschaften vorhandener Klassen auf neue Klassen zu
übertragen,
ein
weiteres
wesentliches
Designmerkmal
objektorientierter
Programmiersprachen. Fehlt diese Fähigkeit, bezeichnet man die Sprache auch als lediglich
objektbasiert.
Obwohl
es
eigentlich
Mehrfachvererbung)
gibt,
zwei
ist
Möglichkeiten
in
Java
nur
der
Vererbung
Einfachvererbung
(einfache
möglich.
Vererbung,
Bei
der
Einfachvererbung wird eine Klasse von maximal einer anderen Klasse abgeleitet. Aber Java
ist keineswegs eingeschränkt in diesem Bereich, denn mit Hilfe von Interfaces ist eine neue
Art der Mehrfachvererbung möglich.
Vererbung ist in Java, und natürlich auch in anderen Programmiersprachen, nur eine
Möglichkeit, um das konkrete Problem in den Computer zu übertragen. Das Prinzip der
Vererbung ist dann anwendbar, wenn zwei Objekte in einer „ist-ein“ oder „ist eine Art von“
Beziehung zueinander stehen. Eine abgeleitete Klasse ist ein Subtyp der zugehörigen
Oberklasse, besitzt also deren Eigenschaften (Daten und Methoden) und erweitert diese bei
Bedarf um neue.
Ableiten einer Klasse:
Wenn man eine neue Klasse aus einer bestehenden ableiten möchte, muss man im Kopf der
Klasse mit Hilfe des Schlüsselworts extends einen Verweis auf die Basisklasse angeben.
Dadurch erbt die abgeleitete Klasse alle Eigenschaften der Basisklasse, d.h. alle Variablen
und alle Methoden. Durch Hinzufügen neuer Elemente oder Überladen der vorhandenen kann
die Funktionalität der abgeleiteten Klasse erweitert werden.
28
class Saeugetier
extends Tier
{
boolean gefaehrlich;
}
Wir können nun nicht nur auf die gefaehrlich verfilmt zugreifen, sondern auch auf alle
Elemente der Basisklasse Tier:
Saeugetier raubtier = new Saeugetier ();
raubtier.name = "Tiger";
raubtier.geburtsjahr = 1985;
raubtier.gewicht = 150;
raubtier. gefaehrlich = true;
System.out.println("Alter = "+ raubtier.alter());
Die Vererbung von Klassen kann beliebig tief geschachtelt werden. Eine abgeleitete Klasse
erbt dabei jeweils die Eigenschaften der unmittelbaren Vaterklasse, die ihrerseits die
Eigenschaften ihrer unmittelbaren Vaterklasse erbt usw.
Besitzt eine Klasse jedoch das Attribut final, ist es nicht erlaubt, eine neue Klasse aus ihr
abzuleiten.
Tier
Fisch
...
Reptil
Säugetier
Raubtier
...
Katze
...
Nagetier
Maus
...
...
Huftier
Pferd
...
Die Superklasse ist die Klasse Tier. Aus ihr werden die drei Klassen Fisch, Reptil und
Säugetier abgeleitet. Aus der Klasse Säugetier werden wiederum die Klassen Raubtier,
Nagetier und Huftier abgeleitet. Und schlussendlich werden noch aus diesen drei Klassen
weitere Unterklassen abgeleitet.
Jede Klasse, die keine extends-Klausel besitzt, wird direkt aus Object abgeleitet. Jede explizit
abgeleitete Klasse stammt am oberen Ende ihrer Vererbungslinie von einer Klasse ohne
explizite Vaterklasse ab und ist damit ebenfalls aus Object abgeleitet. Object ist also die
Superklasse aller anderen Klassen.
29
Überlagern von Methoden:
Eine abgeleitete Klasse erbt nicht nur die Membervariablen, sondern auch alle Methoden der
Vaterklasse. Es dürfen neue Methoden hinzugefügt werden und auch geerbte Methoden
dürfen neu definiert werden. Dies nennt man Überlagerung von Methoden. Nach einer
Überlagerung wird bei einem Aufruf der Methode immer die überlagerte Methode verwendet.
Als einfaches Beispiel erweitern wir die Klasse Saeugetier um die Methode alter und geben
das Alter in Monaten aus:
class Saeugetier
extends Tier
{
boolean gefaehrlich;
public int alter()
{
return 12 * (2002 - geburtsjahr);
}
}
Da die Methode alter schon in der Vaterklasse vorhanden ist, handelt es sich um eine
Überlagerung. In Zukunft würde in allen Objekten von Typ Saeugetier beim Aufruf der
Methode alter die überlagerte Version (also in Monaten berechnet) verwendet werden.
Wird eine Methode x in einer abgeleiteten Klasse überlagert, wird die ursprüngliche Methode
x verdeckt. Aufrufe von x beziehen sich immer auf die überlagernde Variante. Oftmals ist es
allerdings nützlich, die verdeckte Superklassenmethode aufrufen zu können. In diesem Fall
kann mit Hilfe des Ausdrucks super.x() die Methode der Vaterklasse aufgerufen werden.
!
Methoden vom Typ private sind in abgeleiteten Klassen nicht sichtbar und können
daher nicht überlagert werden.
!
Bei Methoden vom Typ final deklariert der Anwender explizit, dass sie nicht
überlagert werden sollen.
!
Auch bei static-Methoden, die ja unabhängig von einer Instanz existieren, besteht
das Problem nicht.
30
2.2.8 Modifier
In
jedem
Java-Programm
werden
bestimmte
Programmelemente
zusammen
mit
Schlüsselwörtern wie public oder private verwendet. Mit Hilfe dieser Attribute können die
Eigenschaften von Klassen, Methoden und Variablen verändert werden. Sie haben
insbesondere Einfluss auf die Lebensdauer, Sichtbarkeit und Veränderbarkeit dieser
Programmelemente und werden meist als Modifier bezeichnet.
Mittels der Sichtbarkeit kann auch der Zugriff auf Methoden und Variablen der Basisklasse
eingeschränkt werden.
Die Sichtbarkeit von Variablen und Methoden wird mit Hilfe folgender Modifier geregelt:
public:
Elemente des Typs public sind in der Klasse selbst (also in ihren Methoden),
in Methoden abgeleiteter Klassen und für den Aufrufer von Instanzen der
Klasse sichtbar.
protected:
Methoden oder Variablen vom Typ protected sind in der aktuellen Klasse
und in abgeleiteten Klassen sichtbar. Darüber hinaus sind sie für Methoden
anderer Klassen innerhalb desselben Pakets sichtbar. Sie sind jedoch nicht für
Aufrufer der Klasse sichtbar, die in anderen Paketen definiert wurden.
private:
Methoden oder Variablen vom Typ private sind nur in der aktuellen Klasse
sichtbar, in allen anderen Klassen bleiben sie dagegen unsichtbar.
Elemente, die ohne einen der drei genannten Modifier deklariert wurden, werden als „package
scoped“ oder Elemente mit Standard-Sichtbarkeit bezeichnet. Sie sind nur innerhalb des
Pakets sichtbar, zu dem diese Klasse gehört. In anderen Paketen sind sie dagegen unsichtbar.
static:
Variablen und Methoden mit dem Attribut static sind nicht an die Existenz
eines konkreten Objekts gebunden, sondern existieren vom Laden der Klasse
bis zum Beenden des Programms. Das static-Attribut beeinflusst bei
Membervariablen ihre Lebensdauer und erlaubt bei Methoden den Aufruf,
ohne dass der Aufrufer ein Objekt der Klasse besitzt, in der die Methode
31
definiert wurde. Wird das Attribut static nicht verwendet, so sind Variablen
innerhalb einer Klasse immer an eine konkrete Instanz gebunden.
final:
Membervariablen mit dem Attribut final dürfen nicht verändert werden, sind
also als Konstanten anzusehen. Methoden des Typs final dürfen nicht
überlagert werden; ebenso wenig dürfen Klassen des Typs final zur Ableitung
neuer Klassen verwendet werden.
2.2.9 Interfaces
Wie schon vorhin erwähnt, gibt es in Java keine Mehrfachvererbung von Klassen.
Andererseits wäre es vorteilhaft, wenn Klassen eine oder mehrere Schnittstellendefinitionen
erben können, und so haben die Designer mit den Interfaces ein Ersatzkonstrukt geschaffen,
das dieses Feature bietet.
Definition und Implementierung:
Ein Interface ist eine besondere Form einer Klasse, die ausschließlich abstrakte Methoden und
Konstanten enthält. Anstelle des Schlüsselwortes class wird ein Interface mit dem Bezeichner
interface deklariert. Alle Methoden eines Interfaces sind implizit abstrakt und öffentlich.
Als Beispiel definieren wir ein Interface Groesse, das die zwei Methoden laenge und hoehe
enthält:
public interface Groesse
{
public int laenge();
public int hoehe();
}
Um die gewünschte Funktionalität zu erhalten, muss das Interface von einer Klasse
implementiert werden. Dazu wird die class-Anweisung um eine implements-Klausel erweitert.
Als Beispiel bauen wir dieses Interface in die Tier-Klasse ein:
public class Tier
implements Groesse
{
32
public String name;
public int geburtsjahr;
public int gewicht;
public int laenge;
public int hoehe;
public int laenge()
{
return this.laenge;
}
public int hoehe()
{
return this.hoehe;
}
}
Wir haben die Klasse dazu um zwei veränderliche Instanzmerkmale erweitert, die es uns
erlauben, die vom Interface geforderten Methoden auf einfache Weise zu implementieren.
Nützlich ist ein Interface immer dann, wenn Eigenschaften einer Klasse beschrieben werden
sollen, die nicht direkt in seiner normalen Vererbungshierarchie abgebildet werden können.
Durch Implementieren des Groesse-Interfaces können sie die Verfügbarkeit der zwei
Methoden laenge und hoehe unabhängig von ihrer eigenen Vererbungslinie garantieren.
3. Swing
3.1 Grundlagen
3.1.1 Abstract Windowing Toolkit (AWT)
Java wurde von Anfang an auch mit dem Anspruch entwickelt, ein vielseitiges, aber einfach
zu bedienendes System für die Gestaltung grafischer Oberflächen zur Verfügung zu stellen.
Diese Grafikbibliothek steht unter dem Namen Abstract Windowing Toolkit (AWT) zur
Verfügung.
Die Fähigkeiten des AWT lassen sich grob in vier Gruppen unterteilen:
!
Grafische Primitivoperationen zum Zeichnen von Linien oder Füllen von Flächen und
zur Ausgabe von Text
!
Methoden zur Steuerung des Programmablaufs auf der Basis von Nachrichten für
Tastatur-, Maus- und Fensterereignisse
33
!
Dialogelemente zur Kommunikation mit dem Anwender und Funktionen zum
portablen Design von Dialogboxen
!
Fortgeschrittenere Grafikfunktionen zur Darstellung und Manipulation von Bitmaps
und zur Ausgabe von Sound
Da die grafischen Fähigkeiten Bestandteil der Sprache bzw. ihrer Klassenbibliothek sind,
können sie als portabel angesehen werden. Unabhängig von der Zielplattform wird ein GUIbasiertes Programm auf allen verwendeten Systemen gleich oder zumindest ähnlich laufen.
Die plattformunabhängige graphische Programmierschnittstelle wird durch das Paket java.awt
realisiert. In diesem Paket sind Klassen und Schnittstellen zum Arbeiten mit Fenstern, Menüs,
Bedienköpfen, usw. zusammengefasst. Die graphische Ausgabe in Fenstern wird durch eine
abstrakte Klasse beschrieben, in der wichtige graphische Ausgabefunktionen zu finden sind.
Auf diese Weise wird die Plattform-Unabhängigkeit von Java – Anwendungsprogrammen
erreicht:
AWT: Eine plattformunabhängige API
Java Virtual Machine
API (Application Program Interface) sind
Programmierschnittstellen für GUI’s)
Plattformspezifisches API
[Quelle: Heinz-Peter Gumm / Manfred Sommer: Einführung in die Informatik]
Das Abstract Windowing Toolkit (AWT) von Java enthält verschiedene Fensterklassen, die
über eine gemeinsame Vererbungshierarchie miteinander in Verbindung stehen. Oberste
Fensterklasse ist Component, aus ihr wird Container abgeleitet. Container ist wiederum die
Oberklasse der beiden Klassen Window und Panel. Während Window sich in die
Unterklassen Frame und Dialog verzweigt, wird aus Panel die Klasse Applet abgeleitet.
Unterhalb von Dialog gibt es noch den Standard-File-Dialog in der Klasse FileDialog.
34
[Quelle: http://developer.java.sun.com]
Beispiel-Applet:
Ein einfacher Rechner zum Addieren und Subtrahieren:
Der Wert im zweiten Textfeld (Eingabe) wird entweder zum Wert des ersten Textfeldes
(Ausgabe) addiert oder von diesem subtrahiert.
AddSub.java:
35
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
Nachdem die benötigten Klasen importiert wurden, wird die Klasse AddSub, die aus Applet
abgeleiten wird, definiert.
public class AddSub
extends Applet
implements ActionListener
{
private TextField ausgabe;
private TextField eingabe;
Die Komponenten werden erzeugt. Den beiden Buttons wird jeweils ein ActionListener
zugewiesen. Ein Klick auf einen Button löst nun ein Ereignis aus.
public void init()
{
setBackground(Color.lightGray);
setLayout(new GridLayout(2, 1));
ausgabe = new TextField("100");
add(ausgabe);
Panel p = new Panel();
p.setLayout(new FlowLayout(FlowLayout.CENTER));
eingabe = new TextField("0");
p.add(eingabe);
Button add = new Button("Addieren");
add.addActionListener(this);
p.add(add);
Button sub = new Button("Subtrahieren");
sub.addActionListener(this);
p.add(sub);
add(p);
}
Hier werden die Aktionen der Buttons definiert. Wenn Button „Addieren“ angeklickt wird, so
wird der Wert des zweiten Textfeldes zum ersten hinzugezählt. Mit dem Button
„Subtrahieren“ wird der Wert des zweiten Textfeldes vom ersten abgezogen.
public void actionPerformed(ActionEvent event)
{
String cmd = event.getActionCommand();
int tf1 = Integer.parseInt(ausgabe.getText());
int tf2 = Integer.parseInt(eingabe.getText());
if (cmd.equals("Addieren")) {
ausgabe.setText("" + (tf1 + tf2));
}
if (cmd.equals("Subtrahieren")) {
ausgabe.setText("" + (tf1 - tf2));
36
}
}
}
Und so sieht der html-Code aus:
<HTML>
<Head>
<Title>AddSub-Applet</Title>
</Head>
<Body>
<H1>AddSub-Applet</H1>
<HR>
<Applet Code="AddSub.class" Width=300 Height=75>
</Applet>
<HR>
</Body>
</HTML>
3.1.2 Vom AWT zum Swing
1. Das Abstract Windowing Toolkit (AWT) des JDK 1.0
Das AWT wurde 1996 mit dem JDK 1.0 eingeführt. Es war nahezu ideal für einfache Web
-Animationen aber ungeeignet für komplexere Anwendungen. Außerdem war das AWT
noch sehr langsam und fehlerhaft. Das Event-Modell war unzulänglich und die Auswahl
an Interaktionsobjekten war sehr gering. Das Look and Feel war noch plattformabhängig.
2. Das Abstract Windowing Toolkit (AWT) des JDK 1.1
Das AWT 1.1 brachte große Verbesserungen im Gegensatz zum AWT 1.0. Es war um
einiges schneller und robuster. Das Programmierkonzept wurde stark verbessert: Java
Beans und der Event-Subscriber-Mechanismus tauchten hier zum Beispiel zum ersten Mal
auf. Leider gab es immer noch zu wenig Interaktionsobjekte.
3. Swing und die Java Foundation Classes (JFC)
Swing wurde im März 1998 eingeführt und ist aus einer Zusammenarbeit von Netscape
und SUN hervorgegangen. Swing wurde komplett in Java verfasst und ist daher
plattformunabhängig. Man spricht von „Lightweight components“ (leichtgewichtige
Komponenten). Endlich gab es auch die vielen neuen Features und Verbesserungen, wie
37
zum Beispiel das „Pluggable Look and Feel“. Des Weiteren wurden das KeyboardHandling und das GUI-Rendering stark verbessert. Zu guter Letzt gab es nun auch eine
Vielzahl neuer Interaktionsobjekte.
3.1.3 Unterschiede AWT - Swing
Zu allererst wäre einmal zu erwähnen, dass Swing auf AWT basiert und noch dessen Event Handling und Layout - Manager verwendet. Jedoch ist Swing um einiges mächtiger. Im
Gegensatz zum AWT benutzen Swing-Komponenten nur noch in sehr eingeschränkter Weise
plattformspezifische GUI-Ressourcen. Abgesehen von Top-Level-Fenstern, Dialogen und
grafischen Primitivoperationen werden alle GUI-Elemente von Swing selbst erzeugt: Zum
Beispiel wird ein Swing-Button unter Windows nicht mehr vom Windows-UI-Manager
dargestellt, sondern von Swing selbst gezeichnet. Statt jeweils plattformspezifisches Look and
Feel anzunehmen, lässt sich mit Swing das LAF dynamisch (auch zur Laufzeit) wechseln. Des
Weiteren ist unter Swing auch der Austausch von Daten zwischen den GUI-Elementen per
Drag&Drop möglich.
Ein bedeutender Unterschied zwischen den AWT- und Swing-Hauptfenstern besteht in ihrer
Komponentenstruktur und den sich daraus ergebenden Unterschieden in der Bedienung.
Während die Komponenten eines AWT-Fensters direkt auf dem Fenster platziert werden,
besitzt ein Swing-Hauptfenster eine einzige Hauptkomponente, die alle anderen
Komponenten aufnimmt.
3.1.4 Vorteile von SWING
! Erstens fallen die plattformspezifischen Besonderheiten weg, und der Code zur
Implementierung der Dialogelemente vereinfacht sich deutlich.
! Zweitens entfallen auch die Unterschiede in der Bedienung. Der Anwender findet auf
allen Betriebssystemen dasselbe Aussehen und dieselbe Bedienung vor.
! Drittens ist Swing nicht mehr darauf angewiesen, Features auf der Basis des kleinsten
gemeinsamen Nenners aller unterstützten Plattformen zu realisieren. Komplexe
Dialogelemente
wie
Bäume,
Tabellen
oder
Registerkarten
können
38
plattformunabhängig realisiert werden und stehen nach der Implementierung ohne
Portierungsaufwand auf allen Systemen zur Verfügung. Tatsächlich stellt Swing eine
sehr viel umfassendere und anspruchsvollere Menge an Dialogelementen als das AWT
zur Verfügung.
3.1.5 Abhängigkeit Swing – AWT
AWT (Abstract Windowing Toolkit) ist der Teil von Java zum Erstellen von User Interfaces
und Zeichnen von Grafiken und Bilder. Es ist ein Satz von Klassen, der zur Verfügung stellen
soll, was ein Entwickler benötigt, um ein grafisches Interface für Java Applets und
Anwendungen
zu
erzeugen.
Die
meisten
AWT
Komponenten
sind
aus
der
java.awt.Component Klasse hergeleitet.
Die Java Foundation Classes (JFC) bestehen aus fünf Hauptteilen: AWT, Swing,
Accessibility, Java 2D und Drag and Drop. Java 2D wurde in AWT integriert. Swing ist auf
AWT aufgebaut. Diese fünf Teile von JFC sind also mit Sicherheit nicht unabhängig von
einander und von Swing wird angenommen, dass es in zukünftigen Versionen von Java
immer mehr mit AWT verschmelzen wird. Drag and Drop wird voraussichtlich in naher
Zukunft auch in Swing und AWT integriert werden. AWT ist das Kerngehäuse von JFC und
ist somit eine der wichtigsten Klassen in Java 2.
Swing ist ein großer Satz von Komponenten beginnend bei sehr einfachen, beispielsweise
Labels, bis zu sehr komplexen Komponenten, wie zum Beispiel Tabellen und Trees. Nahezu
alle Swing Komponenten sind von JComponent hergeleitet, welche die AWT Container
Klasse erweitert. Folglich ist Swing nahezu ein Ersatz für AWT. Swing basiert auf AWT und
nutzt in der Regel noch dessen Event-Handling und Layout-Manager.
3.1.6 Eigenschaften von Swing
Im Gegensatz zum AWT benutzen Swing-Komponenten nur noch in sehr eingeschränkter
Weise plattformspezifische GUI-Ressourcen. Abgesehen von wenigen Ausnahmen (TopLevel-Fenstern, Dialogen und grafischen Primitivoperationen) werden alle GUI-Elemente von
Swing selbst erzeugt.
39
Eine der auf den ersten Blick spektakulärsten Eigenschaften von Swing ist die Möglichkeit,
das Look-and-Feel (also das Aussehen und die Bedienung einer Anwendung) zur Laufzeit
umzuschalten. Dieses als Pluggable Look-and-Feel bezeichnete Feature ermöglicht es
beispielsweise einem Windows-Anwender, zwischen drei unterschiedlichen Look-and-Feels
zu wählen: Swing (Metal), Motif und Windows.
3.1.7 Swing – Package Überblick
javax.swing
Das allgemeinste Swing - Package besteht vor allem aus Komponenten, Adaptern,
Default Komponenten, default component models, und Interfaces für alle delegates
und models.
javax.swing.border
Das Border - Package bestimmt Border Interface und Klassen, welche die einzelnen
Rahmenarten definieren.
javax.swing.colorchooser
Das Colorchooser - Package beinhaltet Unterstüzungsklassen für das color chooser
component.
javax.swing.event
Das Event - Package steht für die Swing spezifischen event types und listeners.
Zusätzlich zu den java.awt.event types können Swing Komponenten ihre eigenen
event types generieren.
javax.swing.filechooser
Das Filechooser - Package beinhaltet Unterstützungsklassen für die file chooser
Komponente.
40
javax.swing.plaf.*
Das „Pluggable Look-and-Feel” (PLAF) - Package beinhaltet die User Interface (UI)
Klassen, welche für das Erscheinungsbild von Swing Komponenten zuständig sind.
javax.swing.table
Das Table - Package beinhaltet Unterstützungsinterfaces und -klassen der Swing
Tabellenkomponente.
javax.swing.text
Das Text - Package beinhaltet Unterstützungsklassen für das Swing document
framework.
javax.swing.text.html.*
Das Text.html - Package beinhaltet Unterstützungsklassen für einen HTML - Renderer
und - Parser.
javax.swing.text.rtf
Das Text.rtf - Package beinhaltet Unterstützungsklassen für ienen grundlegenden Rich
Text Format (RTF) Renderer.
javax.swing.tree
Das Tree - Package beinhaltet Interfaces und Klassen, die die Swing Tree Komponente unterstützen.
javax.swing.undo
Das
Undo
-
Package
stellt
Unterstützungsklassen
zum
Rückgängig/Wiederherstellen - Fähigkeiten in GUI zur Verfügung.
durchführen
der
41
3.2 Container
Jedes Programm, das Swing Komponenten verwendet, hat zumindest einen Top-level
Container. Dieser Top-level Container ist die Wurzel der Hierarchie, die alle innerhalb des
Top-level Containers auftauchenden Swing Komponenten beinhaltet.
Container ist eine abstrakte Klasse. Sie ist dafür zuständig, innerhalb einer Komponente
andere Komponenten aufzunehmen. Container stellt Methoden zur Verfügung, um
Komponenten hinzuzufügen oder sie zu entfernen, und realisiert in Zusammenarbeit mit den
LayoutManager-Klassen die Positionierung und Anordnung der Komponenten.
3.2.1 JFrame
Die Klasse JFrame ist die wichtigste Hauptfensterklasse in Swing. Sie ist aus java.awt.Frame
abgeleitet und stellt ein Hauptfenster mit Rahmen, Systemmenü und Standardschaltflächen
zur Verfügung.
Die Klasse JFrame stellt 2 Konstruktoren zur Verfügung:
Einen zum Erzeugen von Frames ohne Titel und einen weiteren zum Erzeugen von Frames
mit Titel.
42
1.)
public JFrame()
JFrame frame = new JFrame();
2.)
public JFrame(String title)
JFrame frame = new JFrmae („Title Bar“)
Darüber hinaus gibt es noch 2 Konstruktoren zum Erzeugen von Frames, die spezielle
graphische Eigenschaften besitzen.
3.)
public JFrame (GraphicsConfiguration config)
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice gsd[] = ge.getScreenDevices() ;
GraphicsConfiguration gc[] = gsd[0].getConfiguration() ;
JFrame frame = new JFrame(gc[0]) ;
Man könnte natürlich hier ohne weiteres auch eine Titelleiste einfügen.
Wenn man Komponenten zu einem JFrame hinzufügen möchte, muss man die Komponenten
zu JRootPane (bzw. zur ContentPane) hinzufügen. Wenn man Komponenten direkt zu JFrame
hinzufügt, endet dies mit einem Runtime Error.
ein Top-level Container
43
[Quelle: http:// java.sun.com]
3.2.2 JRootPane:
Die Container JFrame, JWindow, JDialog, JApplet und JInternalFrame sind in Swing auf die
RootPane angewiesen. Anstatt Komponenten direkt zum Container hinzuzufügen, fügt man
sie einem Teil der RootPane hinzu. Die RootPane erledigt dann alles Weitere intern.
Während die Komponenten eines AWT-Fensters direkt auf dem Fenster platziert werden,
besitzt ein Swing-Hauptfenster eine einzige Hauptkomponente, die alle anderen
Komponenten aufnimmt.
Diese Hauptkomponente wird als RootPane bezeichnet und ist vom Typ JRootPane. Sie
übernimmt die Rolle einer Art Verwaltungsinstanz für alle anderen Komponenten des
Hauptfensters. Eine RootPane enthält folgende Komponenten:
!
eine aus Container abgeleitete GlassPane und
!
eine aus JLayeredPane abgeleitete LayeredPane
Die LayeredPane enthält ihrerseits zwei Unterkomponenten:
!
eine aus Container abgeleitete ContentPane und
!
eine aus JMenuBar abgeleitete Menüleiste
44
Diese Komponenten stellt sie für JFrame und alle anderen Top-level Container zur
Verfügung.
[Quelle: Guido Krüger: GoTo Java 2]
[Quelle: http:// java.sun.com]
UML Diagramm von JRootPane:
45
JComponent
JRootPane.RootLayout
Component
JRootPane
JMenuBar
JLayeredPane
Container
[Quelle: John Zukovski: Definitive Guide to Swing for Java 2]
Aber in der Regel muss man nicht so genau über die RootPane Bescheid wissen, wenn man
mit Swing Komponenten arbeitet.
3.2.3 JWindow
JWindow ist ebenfalls eine Hauptfensterklasse. Sie dient dazu, ein rahmenloses Fenster zu
erzeugen, das an beliebiger Stelle und in beliebiger Größe auf dem Bildschirm platziert
werden kann.
JWindow besitzt folgende drei Konstruktoren:
1.)
public JWindow()
46
JWindow window = new JWindow();
2.)
public JWindow(Frame owner)
JWindow window = new JWindow(aFrame);
3.)
public JWindow(Window owner)
JWindow window = new JWindow(anotherWindow);
3.2.4 JDialog
In den meisten Fällen besitzt eine Anwendung auch Dialogfenster. Diese werden oft nur
vorübergehend aufgerufen, um eine temporäre Kommunikation zwischen Anwender und
Programm herzustellen. Während ihrer Ausführung wird der Programmfluss angehalten.
Im Unterschied zu Hauptfenstern besitzen Dialogfenster kein Menü und nur eingeschränkte
Systemfunktionen. Zudem ist ihre Größe oft nicht veränderbar.
Dialogfenster besitzen denselben strukturellen Aufbau wie JFrame und JWindow und
implementieren ebenfalls das Interface RootPaneContainer. Auch hier erfolgt also das
Hinzufügen und Anordnen von Komponenten nicht auf dem Fenster selbst, sondern auf seiner
ContentPane.
Einige Konstruktoren von JDialog:
1.)
public JDialog()
JDialog dialog = new JDialog();
2.)
public JDialog (Frame owner)
JDialog = new JDialog(aFrame);
47
3.)
public JDialog (Frame owner, boolean modal)
JDialog = new JDialog(aFrame, false);
4.)
public JDialog (Frame owner, String windowTitle)
JDialog = new JDialog(aFrame, “Hello”);
5.)
public JDialog (Frame owner, String title, boolean modal)
JDialog = new JDialog(aFrame, “Hello“, true);
Als owner sollte der Aufrufer dabei das Fenster übergeben, zu dem der Dialog logisch gehört.
Alle Konstruktoren gibt es auch in einer Form, bei der der owner vom Typ Dialog ist, zum
Beispiel:
public JDialog (Dialog owner)
JDialog = new JDialog(anotherDialog);
Die übrigen Parameter geben den Titel des Dialogs an und legen fest, ob er modal oder nichtmodal sein soll. Bei einem modalen Dialog wird der Aufruf von show (bzw.
setVisible(true))
erst dann beendet, wenn der Dialog geschlossen wurde. Bei einem nicht-
modalen Dialog fährt das Programm dagegen unmittelbar mit der nächsten Anweisung hinter
show fort.
3.2.5 JComponent
Viele der Swing-Komponenten sind direkt oder indirekt aus der Klasse JComponent
abgeleitet. Sie stellt eine Reihe allgemeiner Hilfsmittel zur Verfügung, die für daraus
abgeleitete Komponentenklassen nützlich sind. Als Ableitung von java.awt.Container und
somit auch von java.awt.Component besitzt JComponent bereits einen Großteil der
Funktionalität von AWT-Komponenten. Insbesondere bietet sie als Container die
48
Möglichkeit, andere Komponenten aufzunehmen, und sie kann einen Layout-Manager
besitzen, der für die Größe und Anordnung der enthaltenen Komponenten zuständig ist.
3.2.6 Weitere Container
! JOptionPane
! JApplet
! JInternalFrame
3.3 Komponenten
Die abstrakte Klasse JComponent wird - mit Ausnahme der Hauptfenster - als Basisklasse für
praktisch alle Swing-Komponenten verwendet. JComponent ist direkt aus Container
abgeleitet und besitzt daher alle Eigenschaften der Klassen Component und Container.
Die folgenden Komponenten Hierarchien zeigen die Vielfalt der Komponenten in Swing:
49
[Quelle: http://developer.java.sun.com]
Die Komponenten in der ersten Abbildung sind den Komponenten in AWT ähnlich.
Insgesamt gibt es mehr als doppelt so viele Komponenten in Swing als in AWT.
Hier sind die neueren und erweiterten Komponenten abgebildet:
50
[Quelle: http://developer.java.sun.com]
3.3.1 Panels
51
JPanel ist die Basisklasse für GUI-Container in Swing, die nicht Hauptfenster sind. Sie ist
direkt aus JComponent abgeleitet. JPanel dient dazu, eine Reihe von Dialogelementen unter
Kontrolle eines eigenen Layoutmanagers anzuordnen. Einem JPanel ist standardmäßig ein
FlowLayout als Layoutmanager zugeordnet. Anders als bei den Hauptfenstern gibt es hier
keine ContentPane, sondern die Dialogelemente und der Layoutmanager werden dem Panel
direkt zugewiesen.
public JPanel()
public JPanel(LayoutManager layout)
3.3.2 Label- und Textfelder
Ein JLabel ist ein Dialogelement zur Anzeige einer Beschriftung innerhalb eines GUIContainers. Es kann einen Text und/oder ein Icon enthalten, die in beliebiger Anordnung
dargestellt werden können. Auf Benutzereingaben reagiert ein JLabel nicht.
public JLabel(String text)
public JLabel(Icon image)
public JLabel(String text, Icon icon, int horizontalAlignment)
Die Klasse JTextField stellt ein einzeiliges Textfeld zur Eingabe von Daten dar. Ein Großteil
der Fähigkeiten von JTextField ist in der Basisklasse JTextComponent des Pakets
javax.swing.text implementiert.
Die wichtigsten Konstruktoren von JTextField sind:
public JTextField(int columns)
public JTextField(String text)
public JTextField(String text, int columns)
Der erste von ihnen erzeugt ein leeres Textfeld mit der angegebenen Anzahl Spalten, der
zweite ein Textfeld mit dem angegebenen Text. Beim dritten Konstruktor können sowohl
Spaltenzahl als auch Text vorgegeben werden.
52
3.3.3 Buttons
Swing-Buttons sind Instanzen der Klasse JButton und dienen dazu, Schaltflächen zu
erzeugen.
Ein Button kann wahlweise mit Beschriftung, mit Icon oder mit beidem instanziert werden:
public JButton(String text)
public JButton(Icon icon)
public JButton(String text, Icon icon)
3.3.4 Listen und Comboboxen
Die Klasse JList dient dazu, Listen von Werten darzustellen, aus denen der Anwender einen
oder mehrere Einträge auswählen kann.
public JList()
public JList(Object[] listData)
public JList(Vector listData)
public JList(ListModel dataModel)
Der parameterlose Konstruktor erzeugt eine leere Liste. Wird ein Array oder Vector
übergeben, erzeugt JList aus dessen Daten ein Listenmodell und benutzt es zur Darstellung.
Um den Inhalt der Liste zu definieren, kann auch direkt eine Instanz der Klasse ListModel
übergeben werden. Eine JList wird meist in eine JScrollPane eingebettet, bevor sie zu einem
GUI-Container hinzugefügt wird um die Fähigkeit des Scrollens zu gewährleisten.
53
Eine JComboBox stellt eine Kombination aus Textfeld und Liste dar. Die Liste ist
normalerweise unsichtbar und wird vom Anwender nur dann geöffnet, wenn er einen Wert
daraus auswählen will. Sie erlaubt grundsätzlich nur einfache Selektion.
public JComboBox(Object[] items)
public JComboBox(Vector items)
public JComboBox(ComboBoxModel aModel)
3.3.5 Schieberegler
JScrollBar dient dazu, mit Hilfe eines Schiebereglers einen Wert kontinuierlich innerhalb
vorgegebener Grenzen einzustellen.
public JScrollBar(
int orientation,
int value,
int extent,
int min,
int max
)
Mit orientation wird die Ausrichtung des Schiebereglers festgelegt. Sie kann entweder
horizontal oder vertikal sein. min gibt den kleinsten, max den größten möglichen Wert an. Mit
54
extent wird die Ausdehnung des Schiebers festgelegt. Sie muss mindestens eins, kann aber
auch größer sein. value ist der Anfangswert des Schiebers.
JProgressBar stellt eine Fortschrittsanzeige dar, wie sie auch das Betriebssystem oder ein
Installationsprogramm bei längeren Kopiervorgängen anzeigt.
public JProgressBar(int orient)
public JProgressBar(int min, int max)
public JProgressBar(int orient, int min, int max)
Der Parameter orient gibt die Orientierung der Fortschrittsanzeige an, sie kann wahlweise
horizontal oder vertikal sein. Standardmäßig erzeugt Swing eine horizontale Darstellung. min
und max geben die untere und obere Grenze des Wertebereichs an. Voreinstellung ist 0 bzw.
100.
3.3.6 Menüs
In Swing können alle Hauptfenster mit Ausnahme von JWindow eine Menüleiste haben.
Dabei handelt es sich um eine Instanz der Klasse JMenuBar, die dem Hauptfenster durch
Aufruf von addJMenuBar hinzugefügt wird.
public JMenuBar()
public JMenu add(JMenu c)
Die einzelnen Menüs einer Menüleiste sind Instanzen der Klasse JMenu, die aus JMenuItem
abgeleitet ist. Der Konstruktor erzeugt ein neues Menü mit dem angegebenen Namen. Mit add
werden Menüeinträge hinzugefügt. Meist sind das Instanzen der Klasse JMenuItem, die auf
vielfältige Weise konfiguriert werden können.
public JMenu(String s)
public JMenuItem add(String s)
public JMenuItem add(JMenuItem menuItem)
55
Die Klasse JMenuItem repräsentiert Menüeinträge, also Elemente, die sich in einem Menü
befinden. Da JMenu aus JMenuItem abgeleitet ist, kann ein Menü wiederum Menüs als
Einträge enthalten. Auf diese Weise lassen sich Menüs schachteln.
public JMenuItem(String text)
public JMenuItem(String text, Icon icon)
public JMenuItem(String text, int mnemonic)
3.3.7 Weitere Komponenten
! JTable
! JTree
56
3.4 Look and Feel
Jede Komponente in AWT besitzt eine „schwergewichtige“ peer Klasse, die zwischen einer
JAVA Komponente und einem Betriebssystem Hilfsmittel „vermittelt“. Zum Beispiel sieht
eine java.awt.Button Komponente unter Windows 95 nach einem Windows 95 Button aus,
unter dem Solaris Betriebssystem aber wie ein Motif Button. Jedoch hat der Entwickler
keinen Einfluss auf diesen Prozess.
Swing Komponenten basieren auf „leichtgewichtigen“ Komponenten. Das heißt, sie sind
nicht mehr vom Betriebssystem abhängig. Im Gegensatz zu AWT - Komponenten können
Swing – Komponenten verschieden aussehen auf derselben Plattform.
SWING Look and Feel
AWT Look and Feel
Component
JComponent
(MVC Model)
Peer
(native)
MVC
View
MVC
Controller
ComponentUI (Delegate)
[Quelle: http://developer.java.sun.com]
Platform
Widged
(native)
57
Eine der auf den ersten Blick spektakulärsten Eigenschaften von Swing ist die Möglichkeit,
das Look-and-Feel, also das Aussehen und die Bedienung einer Anwendung, zur Laufzeit
umzuschalten. Dieses als Pluggable Look-and-Feel bezeichnete Feature ermöglicht es einem
Anwender, zwischen drei unterschiedlichen Look-and-Feels zu wählen:
! Swing
! Motif
! Windows
Alle Swing-Komponenten sind so konstruiert, dass es möglich ist, das Look-and-Feel einer
Anwendung zur Laufzeit umzuschalten. Das Programm selbst muss praktisch keinen
zusätzlichen Aufwand treiben, denn das Umschalten wird nach einem einzigen
Methodenaufruf von einem User-Interface-Manager erledigt, der alle nötigen Maßnahmen
koordiniert ausführt.
Um eine Anwendung im Metal – Look darzustellen, muss man folgenden Code verwenden.
try {
UIManager.setLookAndFeel (
"javax.swing.plaf.metal.MetalLookAndFeel");
} catch (java.lang.ClassNotFoundException e) {
}
Das Metal Look and Feel ist Standard in Swing Anwedungen. Es ist ein Versuch ein
gemeinsames Aussehen gegenüber verschiedenen Computer Umgebungen zu erzeugen.
Der folgende Code würde das plattformspezifische Look and Feel verwenden:
try {
UIManager.setLookAndFeel (
UIManager.getCrossPlatformLookAndFeelClassName());
} catch (java.lang.ClassNotFoundException e) {
}
Metal LAF:
Motif LAF:
Windows LAF:
58
3.5 Model-View-Controller
Neben den äußerlichen Qualitäten wurde auch die Architektur des Gesamtsystems verbessert.
Das Anwenden einer Technologie, genannt Model/View/Controller (MVC) – Prinzip, gibt
dem Programmierer die Kontrolle über das Aussehen der Hilfsmittel, wie sie auf Inputs
reagieren und, für einige komplexerer Hilfsmittel, wie Daten dargestellt werden.
MVC ist ein Design Muster, das oft zum Erstellen von User Interfaces (UI) verwendet wird.
Anstatt den gesamten Code in eine einzelne Klasse zu packen, unterscheidet man beim MVCKonzept drei unterschiedliche Bestandteile eines grafischen Elements:
!
Das Modell enthält die Daten des Dialogelements und speichert seinen Zustand.
!
View ist für die grafische Darstellung der Komponente verantwortlich.
!
Der Controller wirkt als Verbindungsglied zwischen beiden. Er empfängt Tastaturund Mausereignisse und stößt die erforderlichen Maßnahmen zur Änderung von
Model und View an.
Das Modell enthält praktisch die gesamte Verarbeitungslogik der Komponente. Ein wichtiger
Aspekt ist dabei, dass ein Model mehrere Views gleichzeitig haben kann. Damit
Veränderungen
des
Modells
in
allen
Views
sichtbar
werden,
wird
ein
Benachrichtigungsmechanismus implementiert, mit dem das Modell die zugeordneten Views
über Änderungen informiert.
Bei den Swing-Dialogelementen wird eine vereinfachte Variante von MVC verwendet, die
auch als Model-Delegate-Prinzip bezeichnet wird. Hierbei wird die Funktionalität von View
und Controller zusammengefasst. Dadurch wird einerseits die Komplexität reduziert und
andererseits die unhandliche Trennung zwischen View und Controller aufgehoben. Es kann
allerdings sein, dass ein Dialogelement mehr als ein Model besitzt. So haben beispielsweise
Listen und Tabellen neben ihrem eigentlichen Datenmodell ein weiteres, das nur für die
Selektion von Datenelementen zuständig ist.
59
3.6 Layout - Manager
In vielen grafischen Oberflächen wird die Anordnung der Elemente eines Dialoges durch
Angabe absoluter Koordinaten vorgenommen. Da Java Programme natürlich auf vielen
unterschiedlichen Plattformen laufen sollen, ist ein Layoutmanager für die Anordnung der
Elemente verantwortlich.
Ein Layoutmanager wird mit der Methode setLayout einem Fenster zugeordnet. Mit add
werden dann die Elemente übergeben und angeordnet.
Die tatsächliche Anordnung der Komponenten auf dem Bildschirm bestimmt in der Regel die
Reihenfolge der Aufrufe der add-Methode des Fensters. Wenn nicht - wie es z.B. beim
BorderLayout möglich ist - zusätzliche Positionierungsinformationen an das Fenster
übergeben werden, ordnet der jeweilige Layoutmanager die Komponenten in der Reihenfolge
ihres Eintreffens an.
! FlowLayout:
Die Dialogelemente werden nebeneinander in einer Zeile angeordnet. Ist in der ersten Zeile
kein Platz mehr vorhanden, wird mit der nächsten fortgefahren.
setLayout(new FlowLayout(FlowLayout.LEFT));
add(new Button("Button 1"));
add(new Button("Button 2"));
add(new Button("Button 3"));
add(new Button("Button 4"));
add(new Button("Button 5"));
60
! GridLayout:
Die Dialogelemente werden in einem rechteckigen Gitter angeordnet. Zeilen- und Spaltenzahl
wird beim Erstellen des Layoutmanagers angegeben.
setLayout(new GridLayout(4,2));
add(new Button("Button 1"));
add(new Button("Button 2"));
add(new Button("Button 3"));
add(new Button("Button 4"));
add(new Button("Button 5"));
add(new Button("Button 6"));
add(new Button("Button 7"));
! BorderLayout:
Die Dialogelemente werden auf die vier Randbereiche und den Mittelbereich des Fensters
verteilt.
setLayout(new BorderLayout());
add("North", new Button("North"));
add("South", new Button("South"));
add("West", new Button("West"));
add("East", new Button("East"));
add("Center", new Button("Center"));
61
! GridBagLayout:
GridBagLayout erweitert die Fähigkeiten von GridLayout und macht es möglich, sehr
komplexe Layouts zu erzeugen.
Wenn die Grundausprägungen der jeweiligen Layoutmanager nicht ausreichen, besteht die
Möglichkeit Layoutmanager zu schachteln. Auf diese Weise kann auch ohne Vorgabe fester
Koordinaten fast jede gewünschte Komponentenanordnung realisiert werden. Sollte auch
diese Variante nicht genau genug sein, so bietet sich schließlich durch Verwendung eines
Null-Layouts die Möglichkeit an, Komponenten durch Vorgabe fester Koordinaten zu
platzieren.
62
3.7 Event Handling
Jedes Mal, wenn ein Anwender etwas schreibt oder einen Mausbutton drückt, ereignet sich
ein Event. Jedes Objekt kann von diesem Event benachrichtigt werden. Alles was es tun hat,
ist das passendes Interface durchzuführen und sich als EventListener für den passenden Event
Source zu registrieren. Swing Komponenten sind in der Lage viele EventListener zu
generieren.
Hier einige Beispiele:
ActionListener
WindowListener
MouseListener
MouseMotionListener
ComponentListener
FocusListener
ListSelectionListener
Anwender klickt einen Button, drückt Return in einem Textfeld oder
wählt einen Menüpunkt aus.
Anwender schließt Frame (Hauptfenster)
Anwender drückt Mausbutton während sich der Cursor über einer
Komponente befindet.
Anwender bewegt die Maus über eine Komponente
Komponente wird sichtbar
Komponente bekommt Tastaturfokus
Tabellen- oder Listenauswahl wechselt
Jedes Event wird von einem Objekt vertreten, das Informationen über das Event enthält und
den Event Source identifiziert. Event Sources sind in den meisten Fällen Komponenten.
Um einen EventListener einzubauen benötigt man einen 3-teiligen Code:
1.) Deklaration der Event - Handler - Klasse:
public class Klasse implements ActionListener {
2.) Registriert eine Instanz aus der Event Handler Klasse als einen Listener für eine oder
mehrere Komponenten:
eineKomponente.addActionListener(InstanzVonKlasse);
63
3.) Führt die Methoden im Listener Interface aus:
public void actionPerformed(ActionEvent e) {
...//Code, der auf die Aktion reagiert...
}
64
4. Beispielprogramme
4.1 Millionenshow
Ich bin mir sicher jedem ist das TV-Quiz „Millionenshow“ ein Begriff. Und genau dieses
Frage-Antwort-Spiel wird hier versucht, in vereinfachter Weise nachzuahmen.
Der Ablauf erweist sich als recht einfach: Aus einer Textdatei, die die Fragen und Antworten
beinhaltet, werden diese ausgelesen. Auf der Benutzeroberfläche erscheint nun die Frage mit
den vier Antwortmöglichkeiten. Nachdem eine Antwort ausgewählt wurde, wird diese mit der
korrekten Antwort verglichen. Stimmen sie überein, so wird der Text „Richtig“ ausgegeben,
andernfalls „Falsch“. Nachdem man eine Frage beantwortet hat, besteht die Möglichkeit eine
neue Frage anzeigen zu lassen.
65
Darstellung der Klassen in UML:
main.java
main.java wird von JBuilder automatisch erzeugt und dient zur Einstellung und Ausrichtung
des Fensters.
package millionenshow;
import javax.swing.UIManager;
import java.awt.*;
public class main {
boolean packFrame = false;
/**Construct the application*/
public main() {
MainScreen frame = new MainScreen();
//Validate frames that have preset sizes
//Pack frames that have useful preferred size info, e.g. from their layout
if (packFrame) {
frame.pack();
}
else {
frame.validate();
}
//Center the window
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Dimension frameSize = frame.getSize();
if (frameSize.height > screenSize.height) {
frameSize.height = screenSize.height;
}
if (frameSize.width > screenSize.width) {
frameSize.width = screenSize.width;
66
}
frame.setLocation((screenSize.width - frameSize.width) / 2,
(screenSize.height - frameSize.height) / 2);
frame.setVisible(true);
}
/**Main method*/
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch(Exception e) {
e.printStackTrace();
}
new main();
}
}
MainScreen.java
Dies ist das Hauptfenster der Anwendung und gleichzeitig der Teil den der Benutzer sieht.
package millionenshow;
Die benötigten Klassen werden importiert.
import java.lang.Math;
import java.util.Random;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import com.borland.jbcl.layout.*;
import java.lang.InterruptedException;
import java.lang.Thread;
Die Klasse MainScreen (aus JFrame abgeleitet) wird definiert. Des Weiteren werden in
diesem Teil die Komponenten erzeugt und die Variablen deklariert.
public class MainScreen extends JFrame {
JPanel contentPane;
XYLayout xYLayout1 = new XYLayout();
JButton jButton1 = new JButton();
JTextArea frage = new JTextArea();
JButton antwort1 = new JButton();
JButton antwort3 = new JButton();
JButton antwort2 = new JButton();
JButton antwort4 = new JButton();
private FragenContainer fc = new FragenContainer();
private int activeQuestion = 1;
67
private Random myRandom = new Random(System.currentTimeMillis());
JButton newQuestion = new JButton();
Der Frame wird aufgebaut.
/**Construct the frame*/
public MainScreen() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}
Den Komponenten werden Eigenschaften und Event-Handler zugewiesen. Das Panel
bekommt ein Layout.
/**Component initialization*/
private void jbInit() throws Exception {
contentPane = (JPanel) this.getContentPane();
jButton1.setText("About");
jButton1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
jButton1_actionPerformed(e);
}
});
jButton1.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseReleased(MouseEvent e) {
jButton1_mouseReleased(e);
}
});
contentPane.setLayout(xYLayout1);
this.setSize(new Dimension(451, 300));
this.setTitle("MillionenShow");
this.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseReleased(MouseEvent e) {
this_mouseReleased(e);
}
});
frage.setText("jTextArea1");
antwort1.setText("jButton2");
antwort3.setText("jButton2");
antwort2.setText("jButton2");
antwort4.setText("jButton2");
newQuestion.setText("Neue Frage");
newQuestion.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseReleased(MouseEvent e) {
newQuestion_mouseReleased(e);
}
});
68
Die Komponenten werden am Panel ausgerichtet.
contentPane.add(jButton1, new XYConstraints(131, 24, 130, 32));
contentPane.add(frage, new XYConstraints(24, 78, 347, 55));
contentPane.add(antwort1, new XYConstraints(27, 151, 133, 34));
contentPane.add(antwort3, new XYConstraints(213, 151, 157, 32));
contentPane.add(antwort2, new XYConstraints(25, 219, 138, 31));
contentPane.add(antwort4, new XYConstraints(212, 219, 157, 32));
contentPane.add(newQuestion, new XYConstraints(309, 28, 116, 29));
Wenn die Maustaste nach anklicken der einzelnen Antwortmöglichkeiten wieder losgelassen
wird, wird die jeweilige Methode aufgerufen.
this.initQuestions();
antwort1.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseReleased(MouseEvent e) {
antwort1_mouseReleased(e);
}
});
antwort2.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseReleased(MouseEvent e) {
antwort2_mouseReleased(e);
}
});
antwort3.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseReleased(MouseEvent e) {
antwort3_mouseReleased(e);
}
});
}
Beim Schließen des Fensters wird automatisch die gesamte Anwendung beendet.
/**Overridden so we can exit when window is closed*/
protected void processWindowEvent(WindowEvent e) {
super.processWindowEvent(e);
if (e.getID() == WindowEvent.WINDOW_CLOSING) {
System.exit(0);
}
}
Diese Methode ist für die Textübergabe von Frage und Antworten zuständig.
protected void initQuestions() {
this.activeQuestion = (Math.abs(this.myRandom.nextInt()) %
this.fc.getAnzahl())+1;
this.frage.setText(this.fc.getFrage(activeQuestion));
this.antwort1.setText(this.fc.getAntwort(activeQuestion,1));
this.antwort2.setText(this.fc.getAntwort(activeQuestion,2));
this.antwort3.setText(this.fc.getAntwort(activeQuestion,3));
this.antwort4.setText(this.fc.getAntwort(activeQuestion,4));
}
69
Die gegebene Antwort wird auf ihre Richtigkeit überprüft. Die Methode erfährt von der unten
folgenden Methode, welche Antwort zu überprüfen ist.
protected void checkAnswere(int which) {
int c = this.fc.getKorrekt(activeQuestion);
if (c==which) this.frage.setText("JUHU");
else this.frage.setText("Ätsch");
this.repaint();
activeQuestion=0;
}
Wenn Button1 angeklickt wird, öffnet dich MainScreenAboutBox.
void jButton1_mouseReleased(MouseEvent e) {
MainScreen_AboutBox m = new MainScreen_AboutBox(this);
m.show();
}
void jButton1_actionPerformed(ActionEvent e) {
}
Hier sind nun die schon zuvor besprochenen Methoden. Wenn Anwort1 gegeben wurde, wird
der Methode „checkAnswere“ der Wert „1“ zurückgeliefert, wenn Antwort2 gegeben wurde,
der Wert „2“, usw.
void antwort1_mouseReleased(MouseEvent e) {
this.checkAnswere(1);
}
void antwort2_mouseReleased(MouseEvent e) {
this.checkAnswere(2);
}
void antwort3_mouseReleased(MouseEvent e) {
this.checkAnswere(3);
}
void this_mouseReleased(MouseEvent e) {
this.checkAnswere(4);
}
Nach Anklicken des newQuestion Buttons wird die Methode initQuestions wieder aufgerufen
und der Frame neu aufgebaut.
void newQuestion_mouseReleased(MouseEvent e) {
this.initQuestions();
this.repaint();
}
}
70
MainScreen_AboutBox.java
MainScreenAboutBox ist das Info-Fenster der Anwendung. Dieses beinhaltet Version und
Copyright der Anwendung.
package millionenshow;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
Die Klasse MainScreenAboutBox wird definiert und ein ActionListener wird implementiert.
public class MainScreen_AboutBox extends JDialog implements
ActionListener {
JPanel panel1 = new JPanel();
JPanel panel2 = new JPanel();
JPanel insetsPanel1 = new JPanel();
JPanel insetsPanel2 = new JPanel();
JPanel insetsPanel3 = new JPanel();
JButton button1 = new JButton();
JLabel imageLabel = new JLabel();
JLabel label1 = new JLabel();
JLabel label2 = new JLabel();
JLabel label3 = new JLabel();
JLabel label4 = new JLabel();
BorderLayout borderLayout1 = new BorderLayout();
BorderLayout borderLayout2 = new BorderLayout();
FlowLayout flowLayout1 = new FlowLayout();
GridLayout gridLayout1 = new GridLayout();
String product = "";
String version = "1.0";
String copyright = "Copyright (c) 2001";
String comments = "";
public MainScreen_AboutBox(Frame parent) {
super(parent);
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
pack();
}
/**Component initialization*/
private void jbInit() throws Exception {
this.setTitle("About");
setResizable(false);
71
panel1.setLayout(borderLayout1);
panel2.setLayout(borderLayout2);
insetsPanel1.setLayout(flowLayout1);
insetsPanel2.setLayout(flowLayout1);
insetsPanel2.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
gridLayout1.setRows(4);
gridLayout1.setColumns(1);
label1.setText("created by chef");
label2.setText(version);
label3.setText(copyright);
label4.setText(comments);
insetsPanel3.setLayout(gridLayout1);
insetsPanel3.setBorder(BorderFactory.createEmptyBorder(10, 60, 10, 10));
button1.setText("Ok");
button1.addActionListener(this);
insetsPanel2.add(imageLabel, null);
panel2.add(insetsPanel2, BorderLayout.WEST);
this.getContentPane().add(panel1, null);
insetsPanel3.add(label1, null);
insetsPanel3.add(label2, null);
insetsPanel3.add(label3, null);
insetsPanel3.add(label4, null);
panel2.add(insetsPanel3, BorderLayout.CENTER);
insetsPanel1.add(button1, null);
panel1.add(insetsPanel1, BorderLayout.SOUTH);
panel1.add(panel2, BorderLayout.NORTH);
}
/**Overridden so we can exit when window is closed*/
protected void processWindowEvent(WindowEvent e) {
if (e.getID() == WindowEvent.WINDOW_CLOSING) {
cancel();
}
super.processWindowEvent(e);
}
/**Close the dialog*/
void cancel() {
dispose();
}
/**Close the dialog on a button event*/
public void actionPerformed(ActionEvent e) {
if (e.getSource() == button1) {
cancel();
}
}
}
72
FragenContainer.java
FragenContainer beinhaltet, wie der Name schon sagt, die gesamten Antworten und Fragen,
die aus einer Textdatei bezogen werden.
package millionenshow;
import java.util.Hashtable;
import java.io.FileInputStream;
import java.io.File;
import java.io.FileReader;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.StringTokenizer;
In der Klasse FragenContainer wird eine Hashtable erzeugt.
public class FragenContainer {
private Hashtable con = new Hashtable();
Methode, die die Fragen ausliest.
public String getAntwort(int frage,int antwort) {
if (antwort==1) return ((Frage)con.get("" + frage)).getAntwort1();
else if (antwort==2) return ((Frage)con.get("" + frage)).getAntwort2();
else if (antwort==3) return ((Frage)con.get("" + frage)).getAntwort3();
else if (antwort==4) return ((Frage)con.get("" + frage)).getAntwort4();
else return "";
}
Methode, die die korrekte Antwort ausliest.
public int getKorrekt(int frage) {
return ((Frage)con.get("" + frage)).getKorrekt();
}
Methode, die die Frage ausliest.
public String getFrage(int frage) {
return ((Frage)con.get("" + frage)).getFrage();
}
Die Größe der Hashtable wird ermittelt.
public int getAnzahl () {
return con.size();
}
73
Aus der Textdatei werden die Informationen herausgelesen und nach Frage, Antworten und
der korrekten Antwort gesucht.
public FragenContainer() {
BufferedReader fs=null;
try {
Auf die Textdatei wird zugegriffen.
fs = new BufferedReader(new InputStreamReader(new FileInputStream("fragen.txt")));
String line;
int j = 1;
boolean readMore = true;
while (readMore) {
line = fs.readLine();
System.err.println(line);
Wenn de Zeile nicht leer ist, wird eine neue Frage erzeugt und der Suchvorgang kann
beginnen. Diese Zeile wird nach Semikolonen abgesucht. Wenn die Anzahl dieser 6 ist, ist der
Teil vor dem ersten Semikolon die Frage, der Text vom 2. bis zum 5.Teil sind die 4
Antworten und der letzte Teil ist schließlich die korrekte Antwort.
if (line!=null) {
Frage f = new Frage();
StringTokenizer st = new StringTokenizer(line,";");
if (st.countTokens()==6) {
int i = 1;
while(st.hasMoreElements()) {
String erg = (String)st.nextElement();
if (i==1) f.setFrage(erg);
else if (i==2) f.setAntwort1(erg);
else if (i==3) f.setAntwort2(erg);
else if (i==4) f.setAntwort3(erg);
else if (i==5) f.setAntwort4(erg);
else if (i==6) f.setKorrekt(Integer.parseInt(erg));
i++;
}
}
Die gesammelten Informationen werden der Hashtable hinzugefügt.
con.put("" + j, f);
j++;
if ((line.length() == 0 )) readMore = false;
} else readMore=false;
}
}
catch(Exception e) {System.err.println(e.toString());}
}
}
74
Frage.java
Eine Frage wird erzeugt.
package millionenshow;
public class Frage {
private String frage = "";
private String antwort1 = "";
private String antwort2 = "";
private String antwort3 = "";
private String antwort4 = "";
private int korrekt = 0;
public Frage(String f, String a1, String a2,String a3,String a4, int c) {
this.frage = f;
this.antwort1 = a1;
this.antwort2 = a2;
this.antwort3 = a3;
this.antwort4 = a4;
this.korrekt = c;
}
public Frage() {
}
Die Frage, die 4 Antwortmöglichkeiten und die korrekte Antwort werden von
FragenContainer eingelesen…
public String getFrage() {return this.frage;}
public String getAntwort1() {return this.antwort1;}
public String getAntwort2() {return this.antwort2;}
public String getAntwort3() {return this.antwort3;}
public String getAntwort4() {return this.antwort4;}
public int getKorrekt() {return this.korrekt;}
… und übergeben.
public void setFrage(String f) {this.frage=f;}
public void setAntwort1(String a1) {this.antwort1=a1;}
public void setAntwort2(String a2) {this.antwort2=a2;}
public void setAntwort3(String a3) {this.antwort3=a3;}
public void setAntwort4(String a4) {this.antwort4=a4;}
public void setKorrekt(int c) {this.korrekt=c;}
}
75
4.2 Ein einfacher Browser
Dieses Beispiel stellt einen sehr einfachen Webbrowser dar. Dieser Browser besteht lediglich
aus einem Text-Fenster (JEditorPane), das den Inhalt der Webpage anzeigt, einem Textfeld
für die URL und einem Button mit dem man zur Startseite zurückkehren kann.
Browser.java
Die Klassen werden importiert.
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;
Die Klasse Browser implementiert einen HyperlinkListener und einen ActionListener.
public class Browser extends JFrame implements HyperlinkListener,
ActionListener {
76
Die Startseite wird festgelegt.
public static void main(String[] args) {
if (args.length == 0)
new Browser("http://www.gym1.at/~skumme16/browser.html");
else
new Browser(args[0]);
}
Variablen werden deklariert.
private JIconButton homeButton;
private JTextField urlField;
private JEditorPane htmlPane;
private String initialURL;
Die Komponenten werden erzeugt und ihnen werden Eigenschaften zugewiesen. Das vom
Betriebssystem verwendete Look and Feel wird eingestellt.
public Browser(String initialURL) {
super("Simple Swing Browser");
this.initialURL = initialURL;
addWindowListener(new ExitListener());
WindowUtilities.setNativeLookAndFeel();
JPanel topPanel = new JPanel();
topPanel.setBackground(Color.lightGray);
homeButton = new JIconButton("home.gif");
homeButton.addActionListener(this);
JLabel urlLabel = new JLabel("URL:");
urlField = new JTextField(30);
urlField.setText(initialURL);
urlField.addActionListener(this);
topPanel.add(homeButton);
topPanel.add(urlLabel);
topPanel.add(urlField);
getContentPane().add(topPanel, BorderLayout.NORTH);
Es wird versucht die Startseite aufzurufen. Gelingt dies nicht, wird eine Fehlermeldung
ausgegeben.
try {
htmlPane = new JEditorPane(initialURL);
htmlPane.setEditable(false);
htmlPane.addHyperlinkListener(this);
JScrollPane scrollPane = new JScrollPane(htmlPane);
getContentPane().add(scrollPane, BorderLayout.CENTER);
} catch(IOException ioe) {
warnUser("Can't build HTML pane for " + initialURL
+ ": " + ioe);
}
77
Die Größe des Fensters wird festgelegt.
Dimension screenSize = getToolkit().getScreenSize();
int width = screenSize.width * 8 / 10;
int height = screenSize.height * 8 / 10;
setBounds(width/8, height/8, width, height);
setVisible(true);
}
Wenn die eingegebene URL mit der Entertaste bestätigt wird, wird versucht diese zu
erreichen. Schlägt dieser Versuch fehl, wird eine Fehlermeldung ausgegeben.
public void actionPerformed(ActionEvent event) {
String url;
if (event.getSource() == urlField)
url = urlField.getText();
else
url = initialURL;
try {
htmlPane.setPage(new URL(url));
urlField.setText(url);
} catch(IOException ioe) {
warnUser("Can't follow link to " + url + ": " + ioe);
}
}
public void hyperlinkUpdate(HyperlinkEvent event) {
if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
try {
htmlPane.setPage(event.getURL());
urlField.setText(event.getURL().toExternalForm());
} catch(IOException ioe) {
warnUser("Can't follow link to "
+ event.getURL().toExternalForm() + ": " + ioe);
}
}
}
private void warnUser(String message) {
JOptionPane.showMessageDialog(this, message, "Error",
JOptionPane.ERROR_MESSAGE);
}
}
WindowsUtilities.java
Dieses Tool erleichtert das Verwenden von Fenstern und Frames in Swing.
import javax.swing.*;
import java.awt.*;
public class WindowUtilities {
public static void setNativeLookAndFeel() {
78
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch(Exception e) {
System.out.println("Error setting native LAF: " + e);
}
}
public static void setJavaLookAndFeel() {
try {
UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName(
));
} catch(Exception e) {
System.out.println("Error setting Java LAF: " + e);
}
}
public static void setMotifLookAndFeel() {
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.motif.MotifLookAndFeel");
} catch(Exception e) {
System.out.println("Error setting Motif LAF: " + e);
}
}
/** A simplified way to see a JPanel or other Container.
* Pops up a JFrame with specified Container as the content pane.
*/
public static JFrame openInJFrame(Container content,
int width,
int height,
String title,
Color bgColor) {
JFrame frame = new JFrame(title);
frame.setBackground(bgColor);
content.setBackground(bgColor);
frame.setSize(width, height);
frame.setContentPane(content);
frame.addWindowListener(new ExitListener());
frame.setVisible(true);
return(frame);
}
/** Uses Color.white as the background color. */
public static JFrame openInJFrame(Container content,
int width,
int height,
String title) {
return(openInJFrame(content, width, height, title, Color.white));
}
/** Uses Color.white as the background color, and the
* name of the Container's class as the JFrame title.
*/
79
public static JFrame openInJFrame(Container content,
int width,
int height) {
return(openInJFrame(content, width, height,
content.getClass().getName(),
Color.white));
}
}
JIconButton.java
Hier wird einem normalen Button ein Icon angefügt.
import javax.swing.*;
public class JIconButton extends JButton {
public JIconButton(String file) {
super(new ImageIcon(file));
setContentAreaFilled(false);
setBorderPainted(false);
setFocusPainted(false);
}
}
ExitListener.java
Bewirkt, dass das Schließen des Frames gleichzeitig auch zum Schließen der Anwendung
führt.
import java.awt.*;
import java.awt.event.*;
public class ExitListener extends WindowAdapter {
public void windowClosing(WindowEvent event) {
System.exit(0);
}
}
80
4.3 Lotto
Dieses Programm lässt eine komplette Lottoziehung nachspielen. Es besteht sowohl die
Möglichkeit selbst Tipps abzugeben aber auch diese automatisch erzeugen zu lassen.
UML – Notation:
81
Anwendung1.java:
Anwendung1.java wird von JBuilder automatisch erzeugt und dient zur Einstellung und
Ausrichtung des Frames.
package lotto;
import javax.swing.UIManager;
import java.awt.*;
public class Anwendung1 {
boolean packFrame = false;
//Die Anwendung konstruieren
public Anwendung1() {
MainScreen frame = new MainScreen();
//Frames überprüfen, die voreingestellte Größe haben
//Frames packen, die nutzbare bevorzugte Größeninformationen enthalten, z.B. aus ihrem Layout
if (packFrame) {
frame.pack();
}
else {
frame.validate();
}
//Das Fenster zentrieren
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Dimension frameSize = frame.getSize();
if (frameSize.height > screenSize.height) {
frameSize.height = screenSize.height;
}
if (frameSize.width > screenSize.width) {
frameSize.width = screenSize.width;
}
frame.setLocation((screenSize.width - frameSize.width) / 2, (screenSize.height - frameSize.height) /
2);
frame.setVisible(true);
}
//Main-Methode
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch(Exception e) {
e.printStackTrace();
}
new Anwendung1();
}
}
82
MainScreen.java:
Das Hauptfenster der Anwendung und gleichzeitig der sichtbare Teil für den Benutzer.
package lotto;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import com.borland.jbcl.layout.*;
import java.util.*;
import javax.swing.event.*;
Die Klasse MainScreen wird definiert, ein ActionListener und ein ChangeListener werden
implementiert. Anschließend werden die Komponenten erzeugt, Variablen deklariert und
Layouts zugewiesen.
public class MainScreen extends JFrame
implements ActionListener, ChangeListener
{
JPanel contentPane;
JMenuBar jMenuBar1 = new JMenuBar();
JMenu jMenuFile = new JMenu();
JMenuItem jMenuFileExit = new JMenuItem();
JMenu jMenuHelp = new JMenu();
JMenuItem jMenuHelpAbout = new JMenuItem();
XYLayout xYLayout1 = new XYLayout();
JPanel jPanel1 = new JPanel();
GridLayout gridLayout1 = new GridLayout();
JPanel jPanel2 = new JPanel();
JButton jButton1 = new JButton();
JButton jButton2 = new JButton();
JButton jButton3 = new JButton();
JPanel jPanel3 = new JPanel();
JList jList1 = new JList();
JList jList2 = new JList();
JPanel jPanel4 = new JPanel();
JLabel jLabel1 = new JLabel();
JSlider jSlider1;
int val = 1;
XYLayout xYLayout2 = new XYLayout();
JButton jButton4 = new JButton();
Vector v = new Vector();
Vector kor = new Vector();
int[] gezogen = new int[6];
int[] tips = new int[6];
int k=1;
JTextField jTextField1 = new JTextField();
JPanel jPanel7 = new JPanel();
JTextField jTextField3 = new JTextField();
XYLayout xYLayout5 = new XYLayout();
83
JLabel jLabel2 = new JLabel();
JLabel jLabel3 = new JLabel();
XYLayout xYLayout3 = new XYLayout();
JLabel jLabel4 = new JLabel();
//Den Frame konstruieren
public MainScreen() {
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}
Die Komponenten werden initialisiert, ihnen werden Eigenschaften zugewiesen.
private void jbInit() throws Exception {
contentPane = (JPanel) this.getContentPane();
contentPane.setLayout(xYLayout1);
this.setSize(new Dimension(1024, 768));
this.setTitle("Lotto");
//Menü
jMenuFile.setText("Datei");
jMenuFileExit.setText("Beenden");
jMenuFileExit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
jMenuFileExit_actionPerformed(e);
}
});
jMenuHelp.setText("Hilfe");
jMenuHelpAbout.setText("Info");
jMenuHelpAbout.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
jMenuHelpAbout_actionPerformed(e);
}
});
//Komponenten
jPanel1.setLayout(new GridLayout(5,9));
jButton1.setText("Tipp abgeben");
jButton1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
}
});
jButton1.addActionListener(this);
jButton2.setText("Zufallstipps erzeugen");
jButton2.addActionListener(this);
jButton3.setText("Ziehung");
jButton3.addActionListener(this);
jLabel1.setText("Anzahl der Zufallstipps:");
contentPane.setPreferredSize(new Dimension(1024, 768));
84
jPanel2.setLayout(xYLayout2);
jButton4.setText("Vergleiche");
jButton4.addActionListener(this);
jPanel7.setLayout(xYLayout5);
jTextField3.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
}
});
jLabel2.setText("Lottotipps:");
jLabel3.setText("1");
jPanel3.setLayout(xYLayout3);
jMenuFile.add(jMenuFileExit);
jMenuHelp.add(jMenuHelpAbout);
jMenuBar1.add(jMenuFile);
jMenuBar1.add(jMenuHelp);
jPanel2.add(jButton1, new XYConstraints(10, 5, 144, -1));
jPanel2.add(jPanel4, new XYConstraints(99, 77, -1, -1));
contentPane.add(jPanel2, new XYConstraints(391, 32, 341, 223));
this.setJMenuBar(jMenuBar1);
for (int i=1; i<46;i++)
{
JCheckBox tip = new JCheckBox(""+i);
tip.addActionListener(this);
jPanel1.add(tip);
}
jPanel3.add(new JScrollPane(jList1), "Center");
//Slider
jSlider1 = new JSlider(JSlider.HORIZONTAL, 0, 20, 1);
jSlider1.setMajorTickSpacing(5);
jSlider1.setMinorTickSpacing(1);
jSlider1.setPaintTicks(true);
jSlider1.setPaintLabels(true);
jSlider1.setSnapToTicks(true);
jSlider1.addChangeListener(this);
jPanel2.add(jTextField1, new XYConstraints(163, 5, 117, 26));
jPanel2.add(jSlider1, new XYConstraints(10, 138, 277, -1));
jPanel2.add(jButton2, new XYConstraints(10, 50, -1, -1));
jPanel2.add(jLabel3, new XYConstraints(161, 107, 40, 21));
jPanel2.add(jLabel1, new XYConstraints(19, 108, 140, -1));
contentPane.add(jPanel1, new XYConstraints(18, 14, 322, 332));
contentPane.add(jPanel3, new XYConstraints(779, 37, 226, 218));
contentPane.add(jLabel2, new XYConstraints(782, 20, -1, -1));
contentPane.add(jPanel7, new XYConstraints(170, 453, 331, 210));
contentPane.add(jButton3, new XYConstraints(32, 405, 112, -1));
contentPane.add(jButton4, new XYConstraints(33, 449, 111, -1));
contentPane.add(jTextField3, new XYConstraints(170, 403, 116, 27));
contentPane.add(jLabel4, new XYConstraints(297, 405, 254, 20));
jPanel7.add(new JScrollPane(jList2));
}
85
Die EventListener werden definiert:
//ActionListener
public void actionPerformed(ActionEvent event)
{
String cmd = event.getActionCommand();
Das Ereignis „Zufallstipps erzeugen“ wird ausgelöst. Die am Schieberegler eingestellte
Anzahl von Tipps wird erzeugt und in der Liste angezeigt. Außerdem werden die einzelnen
Zahlen der jeweiligen Tipps in einem Array gespeichert.
if (cmd.equals("Zufallstipps erzeugen")) {
v.removeAllElements();
for (int j=0;j<val;j++)
{
Ziehung tip = new Ziehung();
v.addElement(""+tip.getReihe());
jList1.setListData(v);
tips[0]=tip.getZahl0();
tips[1]=tip.getZahl1();
tips[2]=tip.getZahl2();
tips[3]=tip.getZahl3();
tips[4]=tip.getZahl4();
tips[5]=tip.getZahl5();
}
}
Hier werden die korrekten Lottozahlen ermittelt und dann n einem Textfeld ausgegeben. Auch
hier werden die einzelnen Zahlen der korrekten Zahlenfolge in einem Array gespeichert.
if (cmd.equals("Ziehung")) {
Ziehung ziehung = new Ziehung();
jTextField3.setText(""+ziehung.getReihe());
gezogen[0]=ziehung.getZahl0();
gezogen[1]=ziehung.getZahl1();
gezogen[2]=ziehung.getZahl2();
gezogen[3]=ziehung.getZahl3();
gezogen[4]=ziehung.getZahl4();
gezogen[5]=ziehung.getZahl5();
}
Der im Lottoschein ausgewählte Tipp wird zur Tippliste hinzugefügt.
if (cmd.equals("Tipp abgeben")) {
v.addElement(jTextField1.getText());
jList1.setListData(v);
}
86
Hier werden die abgegeben Tipps mit den richtigen Lottozahlen verglichen. Die Anzahl der
richtigen wird ausgegeben. Außerdem wird jeder Tipp in einer Liste abgespeichert.
if (cmd.equals("Vergleiche")) {
int n=0;
for (int i=0;i<6;i++)
{
for (int j=i;j<6;j++)
{
if (tips[i] == gezogen[j]){n=n+1;}
}
}
kor.addElement("Bei Ihrem "+k+".Tipp hatten Sie " +n+" richtige!");
k=k+1;
jList2.setListData(kor);
jLabel4.setText("Sie haben "+n+" richtige!");
}
Die ausgewählten Zahlen im Lottoschein werden in ein Textfeld übergeben.
//Checkbox ActionListener
for (int i=1; i<46;i++)
{
if (cmd.equals(""+i)) {
String text = jTextField1.getText();
jTextField1.setText("" +text+ "|"+i);;
}
}
}
Der variable Wert des Schiebereglers wird einem Label übergeben.
//changeListener
public void stateChanged(ChangeEvent event)
{
JSlider jSlider1 = (JSlider)event.getSource();
val = jSlider1.getValue();
if (!jSlider1.getValueIsAdjusting()) {
jLabel3.setText(""+ val);
}
}
Hier werden die Ereignisse im Menü festgelegt. Beim klicken auf „Beenden“ schließt das
Programm, beim Ausführen von „Info“ wird der „About“-Fenster geöffnet.
//Menü
//Aktion Datei | Beenden durchgeführt
public void jMenuFileExit_actionPerformed(ActionEvent e) {
System.exit(0);
}
//Aktion Hilfe | Info durchgeführt
87
public void jMenuHelpAbout_actionPerformed(ActionEvent e) {
Info i = new Info(this);
i.show();
}
//Überschrieben, so dass eine Beendigung beim Schließen des Fensters möglich ist.
protected void processWindowEvent(WindowEvent e) {
super.processWindowEvent(e);
if (e.getID() == WindowEvent.WINDOW_CLOSING) {
jMenuFileExit_actionPerformed(null);
}
}
}
Ziehung.java
In dieser Klasse erfolgt die Erzeugung der Zahlenfolgen.
package lotto;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
public class Ziehung {
int nummer;
String reihe;
int[] lottozahlen = new int [6];
int[] kugel = new int[45];
int[] zahl = new int[6];
int i;
Das Array „Kugel“ wird mit Zahlen von 1-45 aufgefüllt.
public Ziehung()
{
for(int i=0;i<45;i++)
{
kugel[i]=i+1;
}
nummer=0;
reihe="";
Sechs zufällige Zahlen werden aus diesem Array ausgewählt.
for (int i=0;i<6;i++)
{
int zug=(int)((45-nummer)*Math.random());
zahl[nummer]=kugel[zug];
nummer++;
88
for(int k=zug;k<44-nummer;k++)
{
kugel[k]=kugel[k+1];
}
}
Die sechs ausgewählten Zahlen werden sortiert.
for (int j=0;j<5;j++)
{
for(int i=0;i<5;i++)
{
if (zahl[i]>zahl[i+1])
{
int hilf=zahl[i];
zahl[i]=zahl[i+1];
zahl[i+1]=hilf;
}
}
}
Die Zahlen werden aneinandergereiht.
for(int i=0;i<6;i++)
{
reihe=reihe+zahl[i]+"|";
}
}
Die Zahlenreihe wird zurückgeliefert. Auf diese Methode greifen dann die Ereignisse
„Ziehung“ und „Zufallstipps erzeugen“.
public String getReihe()
{
return reihe;
}
Die einzelnen Zahlen der Zahlenreihe werden separat zurückgeliefert. Die beiden oben
genannten Ereignisse benötigen diese Methoden, um die einzelnen Zahlen in ein Array zu
speichern.
public int getZahl0()
{
return zahl[0];
}
public int getZahl1()
{
return zahl[1];
}
89
public int getZahl2()
{
return zahl[2];
}
public int getZahl3()
{
return zahl[3];
}
public int getZahl4()
{
return zahl[4];
}
public int getZahl5()
{
return zahl[5];
}
}
Info.java
Dieses Fenster wird durch Ausführen von „Info“ im Menü geöffnet. Es beinhaltet ledigtlich
vier Labels und einen Button zum Schließen des Fensters.
package lotto;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import com.borland.jbcl.layout.*;
public class Info extends JDialog implements ActionListener {
JPanel panel1 = new JPanel();
JPanel insetsPanel1 = new JPanel();
JPanel insetsPanel3 = new JPanel();
JButton button1 = new JButton();
90
JLabel label1 = new JLabel();
JLabel label2 = new JLabel();
JLabel label3 = new JLabel();
JLabel label4 = new JLabel();
GridLayout gridLayout1 = new GridLayout();
String product = "";
String version = "Version 1.0";
String copyright = "Copyright (c) 2002";
String comments = "";
XYLayout xYLayout1 = new XYLayout();
XYLayout xYLayout2 = new XYLayout();
public Info(Frame parent) {
super(parent);
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
pack();
}
/**Component initialization*/
private void jbInit() throws Exception {
//imageLabel.setIcon(new ImageIcon(MainScreen_AboutBox.class.getResource("[Your Image]")));
this.setTitle("About");
setResizable(false);
panel1.setLayout(xYLayout1);
insetsPanel1.setLayout(xYLayout2);
gridLayout1.setRows(4);
gridLayout1.setColumns(1);
label1.setText("created by Andreas Kamper");
label2.setText(version);
label3.setText(copyright);
label4.setText("Lottoziehung");
insetsPanel3.setLayout(gridLayout1);
insetsPanel3.setBorder(BorderFactory.createEmptyBorder(10, 60, 10, 10));
button1.setActionCommand("Close");
button1.setText("Close");
button1.addActionListener(this);
insetsPanel3.add(label4, null);
insetsPanel3.add(label1, null);
insetsPanel3.add(label2, null);
insetsPanel3.add(label3, null);
panel1.add(button1, new XYConstraints(69, 91, 78, -1));
panel1.add(insetsPanel1, new XYConstraints(0, 143, 400, -1));
panel1.add(insetsPanel3, new XYConstraints(7, 1, -1, -1));
this.getContentPane().add(panel1, BorderLayout.EAST);
}
/**Overridden so we can exit when window is closed*/
protected void processWindowEvent(WindowEvent e) {
if (e.getID() == WindowEvent.WINDOW_CLOSING) {
cancel();
}
super.processWindowEvent(e);
91
}
/**Close the dialog*/
void cancel() {
dispose();
}
/**Close the dialog on a button event*/
public void actionPerformed(ActionEvent e) {
if (e.getSource() == button1) {
cancel();
}
}
}
92
5. Entwicklersoftware
5.1 Borland JBuilder 5.0
JBuilder ist das führende Programm zum Erlernen von Java und visueller Entwicklung. Ein
umfassendes Tutorial hilft Einsteigern sich schnell zurechtzufinden.
93
Mit der WYSIWYG – Oberfläche im Designmodus fällt die graphische Gestaltung leichter.
Mir persönlich hat JBuilder am meisten zugesagt. Das Programm bietet sehr viele Optionen
und ist dennoch komfortabel zu bedienen.
JBuilder 5.0 ist in der Personal Edition als Freeware erhältlich.
94
5.2 SUN Forte 4 JAVA CE 3.0
Forte 4 Java ist in der Community Edition ebenfalls frei erhältlich.
Forte bietet eine ähnliche Design - Oberfläche wie JBuilder. Meiner Meinung nach ist die
Bedienung etwas komplizierter und unübersichtlicher. Forte 4 Java kommt in Sachen Komfort
nicht ganz an den JBuilder heran.
95
5.3 JavaEditor
Der JavaEditor ist meiner Meinung nach ein ideales Einsteigerprogramm für Java, weil die
Entwicklungsumgebung sehr übersichtlich und wenig komplex ist. Für das Programmieren
von Swing-Anwendungen bzw. von Programmen, bei denen auch auf die graphische
Oberfläche Wert gelegt werden muss, ist der JavaEditor allerdings nicht so zu empfehlen.
Zumindest steht er IDE’s wie JBuilder 5.0 oder Forte 4 Java 3.0 nach, weil JavaEditor keine
WYSIWYG Oberfläche besitzt. Aus diesem Grund wird die graphische Gestaltung auch um
einiges schwieriger.
96
6. Literaturverzeichnis
Folgende Quellen wurden von mir beim Erstellen dieser Fachbereichsarbeit verwendet:
Bücher
KRÜGER, Guido:
GoTo Java 2 – Handbuch der Java-Programmierung.
2.Auflage.
München: Addison-Wesley, 2000
ZUKOWSKI, John:
Definitive Guide to Swing for Java 2, Second Edition.
Berkeley: Apress, 2000
GUMM, Heinz-Peter, SOMMER Manfred:
Einführung in die Informatik.
4.Auflage.
München: Oldenbourg, 2000
MÖSSENBÖCK, Hanspeter:
Sprechen Sie Java?.
Eine Einführung in das systematische Programmieren.
Heidelberg: dpunkt.verlag, 2001
TABATT Peter, WOLF Henry:
Java programmieren mit JBuilder 4
Frankfurt: Software & Support, 2001
Internet
http://java.about.com
http://www-lufgi3.informatik.rwth-aachen.de
http://developer.java.sun.com
http://www.selfjava.de/
http://ada.rg16.asn-wien.ac.at
97
Ich bestätige, dass ich diese Fachbereichsarbeit selbstständig unter ausschließlicher
Verwendung der oben angeführten Quellen erstellt habe.
Herunterladen