Hans Wypior Februar 2007 Einführung in die Programmiersprache JAVA Inhalt 1. Allgemeines 2. Konsolenapplikationen • • • • • • Input-Output-Datenströme Datentypen Operatoren Modularisierung durch Klassen und Methoden Kontrollstrukturen, Fehlerbehandlung Datenstrukturen 3. Fensterapplikationen • Ereignisbehandlung • Layout-Manager 4. Applets • Besonderheiten • Threads 5. Nützliches und Wissenswertes • Drucken • Grafik 6. Quellen Wypior Seite 1 Stand: 10.02.2007 Einführung in die Programmiersprache JAVA Allgemeines Java ist eine plattformunabhängige Programmiersprache. Diese Unabhängigkeit wird dadurch erreicht, dass zunächst aus einem Quelltext mit Hilfe eines Compilers ein sogenannter Bytecode erzeugt wird, der dann von einem computersystemabhängigen Interpreter abgearbeitet wird. Compiler (JAVAC) und Interpreter (JAVA) werden beim Download von Java mitgeliefert. Der Quelltext läßt sich mit jedem Editor erstellen. Java ist eine streng objekt-orientierte Programmiersprache. Sie gestattet die Programmierung von eigenständigen Anwendungen mit und ohne Fenstertechnik und von Applets, die in einem Browser oder einem Applet-Viewer ablaufen. Das gleiche Beispiel in 3 Versionen Versionen Das Programm "HalloApplet.class" mit der Ausgabe "Hallo Welt" wird in einem Browser unmittelbar gestartet. Als eigenständiges Programm mit der Ausgabe des Textes in einem Fenster ist der Aufruf des Programms "HalloFenster.class" mit Hilfe des Interpreters erforderlich: "java HalloFenster", wobei "HalloFenster.class" vorher mit dem Aufruf "javac HalloFenster.java" aus dem Quelltext "HalloFenster.java" erzeugt wurde. Sinngemäß gilt letzteres auch für das Programm "HalloWelt.class", das die Ausgabe im Konsolen-Fenster vornimmt. Beispiel 1: Das Programm "Hallo Welt" als Applet 1. import java.awt.*; 2. import java.applet.*; 3. public class HalloApplet extends Applet 4. { 5. public void paint(Graphics g) 6. { 7. g.drawString("Hallo Welt!",5,30); 8. } 9. } 10. Der Java-Compiler erzeugt die Datei HalloApplet.class. Die neue Klasse muss jetzt in eine WWW-Seite eingebunden werden, zum Beispiel so: <HTML> <HEAD> <TITLE> "Titel" </TITEL> </HEAD> <BODY> "Das ist ein Applet!" <APPLET CODE=HalloApplet.class WIDTH=150 HEIGHT=25> </BODY> </HTML> Wypior Seite 2 Stand: 10.02.2007 Einführung in die Programmiersprache JAVA Das Programm als Frame 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. import java.awt.*; 11. 12. 13. 14. public void paint(Graphics g) { g.drawString("Hallo Welt!",100,100); } public class HalloFenster extends Frame { public HalloFenster(String Titel) //Konstruktor { super(Titel); //Konstruktor des Elternobjektes aufrufen setSize(300,200); //Größe festlegen show(); //geerbte show-Methode ruft paint-Methode auf } 15. 16. 17. 18. 19. public static void main(String args[]) { HalloFenster MyWindow = new HalloFenster("Hallo Welt"); } } Das Programm im Konsolen-Fenster 1. class HalloWelt 2. { 3. public static void main(String[] args) 4. { 5. System.out.println("Hallo Welt!"); 6. } 7. } Input-Output-Datenströme im Konsolen-Fenster Damit ein Computer mit seiner Außenwelt (Peripherie) kommunizieren kann, bedarf es sogenannter Input-Output-Schnittstellen (kurz: IO-Schnittstellen). Das Package java.io dient der programmtechnischen Umsetzung und muß immer dann eingebunden werden, wenn Daten von der Tastatur gelesen werden sollen. Die Kommunikation findet über Datenströme statt. Dabei gibt es drei Standard-Datenströme: • • • System.in — der Eingabestrom System.out — der Ausgabestrom System.err — der Ausgabestrom für Fehlermeldungen. Normalerweise ist System.in mit der Tastatur verbunden und die Daten sind vom Typ Character. System.out und System.err sind beide mit dem Bildschirm verbunden und beide sind ebenfalls Character-Daten. Beispiel 2: Wypior Seite 3 Stand: 10.02.2007 Einführung in die Programmiersprache JAVA Das folgende Programm liest Zeichen von der Tastatur in den String mit dem Namen Mitteilung ein und sendet sie anschließend zum Bildschirm. import java.io.*; class ioDemo { public static void main (String[] args) throws IOException { String Mitteilung; InputStreamReader holDaten = new InputStreamReader(System.in); BufferedReader Eingabe = new BufferedReader(holDaten); System.out.println("Mitteilung: "); Mitteilung = Eingabe.readLine(); System.out.println("Es liegt folgende Nachricht vor: " + Mitteilung ); } } Um die Bedeutung und Arbeitsweise der beiden Objekte InputStreamReader und BufferedReader zu verstehen, kann man sich den Ablauf der Vorgänge bei der Tastatureingabe klar machen: Wenn ein Benutzer eine Taste anschlägt, wird hardware-seitig ein Interrupt ausgelöst, der dazu dient, das laufende Programm kurz zu unterbrechen, die Tastatureingabe entgegenzunehmen und den Code der Taste im sogenannten Tastaturpuffer abzulegen. Diese Vorgehensweise ist notwendig, weil das Programm, das die Eingabe verarbeiten soll, eventuell noch gar nicht an der Stelle angekommen ist, an der der Tastendruck erwartet wird. Damit ist die Bedeutung der Objekte klar: Der InputStreamReader nimmt die Daten von der Datenquelle (z.B. Tastatur) entgegen, schreibt sie in einen Puffer und erhöht einen Zeiger, der angibt, wieviele gültige Zeichen im Puffer stehen. Der BufferedReader liest die gepufferten Daten aus und setzt den Pufferzeiger zurück. BufferedReader und InputStreamReader arbeiten also eng zusammen und teilen sich die Aufgabe der Datenerfassung. Im Programm kann man auch die folgende kürzere Schreibweise verwenden, wobei der Name für den InputStreamReader eingespart wird: BufferedReader Ein = new BufferedReader(new InputStreamReader(System.in)); Die Methode readLine des BufferedReader's erzeugt aus den gepufferten Daten schließlich einen String. Jeder IO-Vorgang kann Fehler nach sich ziehen. Mittels throws IOException wird standardmäßig eine Fehlerbehandlungsroutine aufgerufen. Die Fehlerbehandlung ist bei Lese-Operationen zwingend notwendig. Deshalb muss ein möglicher Fehler entweder weiter gereicht oder in der Methode mit Hilfe eines try – catch – Blockes behandelt werden, in der er auftritt. Wypior Seite 4 Stand: 10.02.2007 Einführung in die Programmiersprache JAVA Datentypen JAVA ist streng typisiert. Das heißt, jede Variable muss vor der ersten Verwendung im Programm bereits von ihrem zukünftigen Inhalt her festgelegt werden (Zahl, Buchstabe), und kann nachher keine anderen Datentypen mehr aufnehmen. Gleiches gilt für Rückgabewerte und Übernahmeparameter von Methoden. Zahlentypen Typ byte short int long float double Minimalwert Maximalwert -128 +127 -32.768 +32.767 -2.147.483.648 +2.147.483.647 -9.223.372.036.854.775.808 +9.223.372.036.854.775.807 1,40239846 * 10-45 3,40282347 * 1038 4,94065645841246544 * 10-324 1,79769313486231570 * 10308 Logische Werte Werte JAVA kennt den logischen Datentyp boolean mit den zugehörigen Konstanten true und false. Zeichentyp Der JAVA-Zeichentyp char dient zur Aufnahme eines Unicode-Zeichens und belegt daher im RAM 2 Byte. Dadurch ist es möglich, auch chinesische und japanische Schriftzeichen zu erfassen. Die ersten 256 Zeichen entsprechen dem ASCII-Code Einige Sonderzeichen können durch Escape-Sequenzen eingegeben werden: Sequenz \ \n \b \r \f \t \\ \' \" \xdd \ddd \uddd Wypior Bedeutung Neue Zeile LF oder CR+LF (Zeilentrenner, abhängig vom Betriebssystem) BS (Backspace) CR (Wagenrücklauf) FF (Formfeed) Tab (Tabulator) Das Zeichen \ Einfaches Anführungszeichen ' Zweifaches Anführungszeichen " ASCII-Codiertes Zeichen in Hex-Schreibweise ASCII-Codiertes Zeichen Unicode-Zeichen in Hex-Schreibweise Seite 5 Stand: 10.02.2007 Einführung in die Programmiersprache JAVA Typumwandlung Sequenz int x = 4711; double y; y = x; int x; double y = 3.75; x = y; int x; double y = 3.75; x = (int)y; int x,x; short z; x=30000; y=30000; z = (short) (x+y); int x,y; double z1,z2; x = 3; y = 4; z1 = x/y; z2 = 3/4; int x,y; double z1,z2; x = 3; y = 4; z1 = (double) x/y; z2 = (double) 3/4; Ergebnis Kommentar Umwandlung möglich y = 4711.0 Umwandlung nicht möglich --explizite Typumwandlung möglich , Nachkommastellen werden abgeschnitten. Umwandlung möglich, Ergebnis wegen Bereichsüberschreitung falsch x = 3 z = -5536 Umwandlung möglich, Ergebnis unerwartet: da x und y ganzzahlig sind, wird zuerst das Ergebnis 0,75 ganzzahlig zu 0 gemacht. Anschließend erfolgt die Typumwandlung Umwandlung möglich, Ergebnisse korrekt z1 = 0.0 z2 = 0.0 z1 = 0.75 z2 = 0,75 Operatoren Arithmetische Operatoren Operator Benutzung + a+b a-b / a/b * a*b % a%b ++ a++ ++ ++a -- a-- -- --a Wypior Beschreibung addiert b und a subtrahiert b von a dividiert a durch b multipliziert a mit b ergibt den ganzzahligen Rest der Divison von a durch b erhöht a um 1, Rückgabewert ist a vor der Erhöhung erhöht a um 1, Rückgabewert ist a nach der Erhöhung erniedrigt a um 1, Rückgabewert ist a vor der Erniedrigung erniedrigt a um 1, Rückgabewert ist a nach der Erniedrigung Seite 6 Stand: 10.02.2007 Einführung in die Programmiersprache JAVA Vergleichsoperatoren Operator Benutzung < a<b > a>b <= a<=b >= a>=b == a==b != a!= Logische Verknüpfungsoperatoren Operator Benutzung && a&&b || a||b & a&b | a|b ~ ~a Zuweisungsoperatoren Operator Benutzung = a=b += a+=b -= a-=b *= a*=b /= a/=b %= a%=b Beschreibung liefert true, wenn a kleiner als b ist liefert true, wenn a größer als b ist liefert true, wenn a kleiner oder gleich b ist liefert true, wenn a größer oder gleich b ist liefert true, wenn a gleich b ist liefert true, wenn a ungleich b ist Beschreibung logisches UND: verknüpft zwei Aussagen, liefert true, wenn beide Aussagen wahr sind logisches ODER: liefert true, wenn eine der Aussagen oder beide wahr sind bitweises UND: a = 0001, b = 0101 a & b = 0001 bitweises ODER: a = 0001, b = 0110 a | b = 0111 bitweises Komplement einer Zahl a = 0001 ~a = 1110 Beschreibung weist der Variable den Wert von b zu bedeutet a=a+b bedeutet a=a-b bedeutet a=a*b bedeutet a=a/b bedeutet a=a%b Modularisierung durch Klassen und Methoden Java-Programme bestehen aus Klassendefinitionen. Eine Klasse ist ein Bauplan für Objekte, wobei diese Objekte wie Dinge der realen Welt aufgefasst werden können. Jedes einzelne Objekt wird als Instanz der Klasse bezeichnet. Klassen bestehen aus Attributen (Eigenschaften) und Methoden (Funktionen und Prozeduren). Allgemeiner Aufbau einer Klasse: [Modifizierer] class Klassenname [extends Basisklasse] [implements Schnittstellen] { Attributdeklarationen Methodendeklarationen } Wypior Seite 7 Stand: 10.02.2007 Einführung in die Programmiersprache JAVA Die in eckigen Klammern angegebenen Einheiten sind optional. Modifizierer schränken die Verwendung der Klasse ein, Basisklasse (Elternklasse) ist die Klasse, von der die vorliegende Klasse abgeleitet wurde. Schnittstellen stehen für Interfaces. Statische Attribute und Methoden Attribute, die mit dem Schlüsselwort static versehen wurden, sind sogenannte Klassenvariable. Von ihnen gibt es nur ein einziges Exemplar, unabhängig davon, wie viele Instanzen der Klasse existieren. Der Zugriff von außen kann über Klassenname.Variablenname erfolgen. Statische Methoden heißen entsprechend Klassenmethoden. Klassenmethoden benötigen keine Instanz für ihren Aufruf. Ein Zugriff auf Instanzvariablen ist nicht möglich. Modifizierer von Klassen, Attributen Attributen und Methoden Modifizierer Klasse Attribut Methode Konstruktor Besonderheiten public Nutzung von allen Packages mög× × × × lich, in einer Quelldatei darf höchstens eine Klasse public sein. protected Zugriff von allen Klassen des eige× × × nen Pagages möglich private Zugriff nur in der sie definierenden × × × Klasse möglich static nur ein Exemplar pro Klasse vor× × handen, Methoden benötigen keine Instanz final Keine Subklassen ableitbar, Attribu× × × te sind nicht veränderbar abstract Keine Instantiierung möglich, Basis× × klassen für Vererbung, Subklassen müssen sie überschreiben native Abstrakte Deklaration, Die Imple× mentierung erfolgt in anderen Programmiersprachen synchronized Synchronisierung von Threads × Programme, die Teilprobleme in Form von Methoden lösen, sind besser lesbar, besser wartbar, leichter zu debuggen und der modulare Code ist besser wiederzuverwerten. Im nachfolgenden Beispiel wird die Zinseszinsberechnung in einer eigens dafür konstruierten Methode durchgeführt. Wypior Seite 8 Stand: 10.02.2007 Einführung in die Programmiersprache JAVA Beispiel 3: Berechnung eines Kapitals mittels Zinseszinsrechnung. 1. 2. 3. public class CZinseszins { public static double Zinsberechnung(double Anfangskapital, double Zinssatz, double Laufzeit) 4. 5. { double Endkapital; 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. Endkapital = Anfangskapital * Math.pow((1 + Zinsatz/100),Laufzeit); return Endkapital; } public static void main(String[] args) { double Endkapital; Endkapital = Zinsberechnung(15000,3.5,7); System.out.println("Kapital nach 7 Jahren: " + (int) Endkapital); } } Sinn der Klassenbildung in der objektorientierten Programmierung ist es zum einen, Objekte der realen Welt zu repräsentieren bzw. nachzuempfinden. Klassen können aber auch als Container für eine Sammlung von Methoden dienen (wie z.B. bei der Java-Klasse java.lang.Math). Sinnvoll im Sinne der Wiederverwertbarkeit ist es, Klassen in eigenen Packages zu organisieren. Um z.B. eine Klasse CSparbuch in einem Package namens Zinsrechnung abzulegen, muss die Klassendefinition in einer eigenen Quelldatei vorhanden sein. Dieser wird dann die Anweisung package Zinsrechnung; vorangestellt. Bei der Erstellung von Packages sind folgende Punkte zu beachten: • Der Name eines Packages muss mit einem namensgleichen Verzeichnis übereinstimmen, in dem die zum Package gehörenden Klassen gespeichert sind. • Klassen eines Packages können nur dann auf Klassen eines anderen Packages zugreifen, wenn die aufgerufenen Klassen als public deklariert wurden. Um in einem Programm die im Package abgelegten Klassen nutzen zu können, ist es erforderlich, eine import-Anweisung aufzunehmen. Wypior Seite 9 Stand: 10.02.2007 Einführung in die Programmiersprache JAVA Beispiel 4: Im Programm CHoheKante sollen Methoden der Klasse CSparbuch, die im Package Zinsrechnung gespeichert ist, aufgerufen werden. 1. package Zinsrechnung; 2. 3. 4. 5. public class CSparbuch { double kapital; double zinssatz; 6. 7. 8. 9. 10. public CSparbuch(double kap, double zinsen) { kapital = kap; zinssatz = zinsen; } 11. 12. 13. 14. public void einzahlen(double betrag) { kapital += betrag; } 15. 16. 17. 18. public void abheben(double betrag) { kapital -= betrag; } 19. 20. 21. 22. public double zinseszins(double laufzeit) { return kapital*Math.pow((1 + zinssatz/100),laufzeit); } 23. 24. 25. 26. 27. public double zins(double laufzeit) { return kapital * (1+ zinssatz/100 * laufzeit); } } Der Aufruf der Methoden der Klasse CSparbuch erfolgt nun im Programm CHoheKante: 1. // Datei CHoheKante.java 2. import Zinsrechnung.CSparbuch; 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. public class CHoheKante { public static void main(String[] args) { CSparbuch Sparbuch = new CSparbuch(0,3); Sparbuch.einzahlen(10000); System.out.println("Ertrag nach 5 Jahren :"); System.out.println("\t ohne Zinseszins: " + (int) Sparbuch.zins(5)); System.out.println("\t mit Zinseszins: " + (int) Sparbuch.zinseszins(5)); } } Wypior Seite 10 Stand: 10.02.2007 Einführung in die Programmiersprache JAVA Wichtige Packages Java hat selbst keine E/A-Routinen. Es gibt jedoch einige vorgefertigte Bibliotheken in Form von Packages. Zum Beispiel: • • • • • • java.lang: Allgemeine Klassen für Java: Runnable, Boolean, System usw. Dieses Package wird als einziges immer implizit importiert. java.util: Hilfsklassen: Date, Vector, Hashtable java.io: E/A Klasse: File, InputStream, OutputStream awt: Abstract Window Toolkit: Benutzerinterfaceklassen net: Netzwerkspezifische Klassen applet: enthält die Klassen Applet und AudioClip für Audioanwendungen. Kontrollstrukturen, Fehlerbehandlung Zu den Kontrollstrukturen eines Programms gehören Schleifen und Bedingungen, wobei leztere Programmverzweigungen zur Folge haben. Beispiel 5: Das nachfolgende Programm zeigt den Gebrauch einer Zählschleife, sowie den Einsatz von Datenfeldern und Fehlerkontrolle. Ein Datenfeld mit 100 Elementen bestehend aus ganzen Zahlen wird mit Werten gefüllt. Gleichzeitig werden Index und Inhalt ausgegeben. Bei Feldern beginnt der Index grundsätzlich bei 0. Ein falscher Zugriff würde eine Exception auslösen und das Programm zum Absturz bringen. Dies wird durch die Fehlerkontrolle verhindert. // Datei CExceptionTest.java public class CExceptionTest { public static void main(String[] args) { int i; int[] feld = new int[20]; //Datenfeld mit 20 Elementen vom Typ int // hier kann ein Fehler auftreten, also absichern try { for( i = 0; i<= 20; i++) //bei i=100 erfolgt ein illegaler Zugriff { feld[i] = (int) Math.round(Math.random()*100); System.out.println ("Element Nr "+i+" hat den Wert " + feld[i] +"\n"); } } // hier ist die Fehlerbehandlung catch(ArrayIndexOutOfBoundsException e) { System.out.println("Ein illegaler Zugriff!\n"); } } } Wypior Seite 11 Stand: 10.02.2007 Einführung in die Programmiersprache JAVA Beispiel 6: Beim Einlesen von Daten aus Dateien, wozu auch die Eingabe über die Tastatur gehört, ist eine Fehlerbehandlung zwingend vorgeschrieben. Dies kann wie im nachfolgenden Beispiel explizit geschehen oder durch Weiterreichen an die Standardfehlerbehandlungsroutine von Java (siehe Beispiel 7). import java.io.*; import java.util.*; //ein eingelesener String wird in Großbuchstaben gewandelt class CBit5Demo { InputStreamReader holDaten; BufferedReader Eingabe; public CBit5Demo() //Konstruktor { holDaten = new InputStreamReader(System.in); Eingabe = new BufferedReader(holDaten); System.out.println("Umwandlung eines Textes in Grossbuchstaben"); System.out.println("------------------------------------------\n"); } public String eingabe() { String text="Bitte einen Text eingeben\n"; System.out.println(text); String Mld; try { Mld = Eingabe.readLine(); //der Fehlerabfrageblock ist hier } //zwingend erforderlich catch (IOException e) { Mld = "Es ist ein Fehler aufgetreten!"; } return Mld; } public static void main (String[] args) { String Mitteilung; StringBuffer Wandeltext = new StringBuffer(); byte[] feld = new byte[255]; CBit5Demo bit5Demo = new CBit5Demo(); Mitteilung = bit5Demo.eingabe(); feld = Mitteilung.getBytes(); for (int i=0; i<Mitteilung.length(); i++) { if (feld[i]>=97 && feld[i]<=122) //ASCII-Code kleiner Buchstaben { feld[i] = (byte) (feld[i] & (0xDF)); //Bit 5 ist 0 } Wandeltext.append((char)feld[i]); } System.out.println("\n\n\nAlles in Grossbuchstaben:\n "); System.out.println(Wandeltext.toString()); } } Wypior Seite 12 Stand: 10.02.2007 Einführung in die Programmiersprache JAVA Beispiel 7: Dieselbe Aufgabe kann einfacher gelöst werden, da die Methode zum Umwandeln in Großbuchstaben in Java implementiert ist. Nachfolgend wird von der Standard-Fehlerbehandlung Gebrauch gemacht: import java.io.*; //ein eingelesener String wird in Großbuchstaben gewandelt class CGrossbuchstaben { InputStreamReader holDaten; BufferedReader Eingabe; public CGrossbuchstaben() //Konstruktor { holDaten = new InputStreamReader(System.in); Eingabe = new BufferedReader(holDaten); System.out.println("Umwandlung eines Textes in Grossbuchstaben"); System.out.println("------------------------------------------\n"); } public String eingabe() throws IOException { String Mld; String text="Bitte einen Text eingeben\n"; System.out.println(text); Mld = Eingabe.readLine(); return Mld; } public static void main (String[] args) throws IOException { CGrossbuchstaben gb = new CGrossbuchstaben(); StringBuffer Wandeltext = new StringBuffer(); String Mitteilung = gb.eingabe(); System.out.println("\n\n\nAlles in Grossbuchstaben:\n "); System.out.println(Mitteilung.toUpperCase()); } } Datenstrukturen Arrays Die Deklaration eines Datenfeldes erfolgt in der Form Typ[] Arrayname; Zur Erzeugung wird die new-Anweisung benutzt. new legt die Größe des Arrays fest und muß einen ganzzahligen Wert liefern. ehrdimensionale Arrays sind möglich und werden als geschachtelte Arrays angelegt. Dateien Wie schon erwähnt, gehört das Datei-Handling ebenfalls zu den Input-Output-Vorgängen und ähnelt dem Vorgehen beim Einlesen von der Tastatur und der Ausgabe auf den Bildschirm. Wypior Seite 13 Stand: 10.02.2007 Einführung in die Programmiersprache JAVA Beispiel 8: Erzeugen von Zufallszahlen und Speichern der Zahlen in eine Datei. import java.io.*; import java.util.*; public class CDateiSchreiben { public static void main(String[] args) { try { int zahl; Random zufall = new Random(); FileWriter aus = new FileWriter("Zahlen.dat"); zahl = zufall.nextInt(50); while(zahl != 20) { aus.write(zahl); System.out.println(zahl); zahl = zufall.nextInt(50); } aus.close(); } catch (IOException e) { System.out.println("Fehler mit Datei: " + e.getMessage()); } } } Beispiel 9: Lesen von Zahlen aus einer Datei und Anzeige auf dem Bildschirm. import java.io.*; import java.util.*; public class CDateiLesen { public static void main(String[] args) { try { int zahl; FileReader ein = new FileReader("Zahlen.dat"); while((zahl=ein.read()) != -1) { System.out.println(zahl); } ein.close(); } catch (IOException e) { System.out.println("Fehler beim Lesen der Datei"); } } } Wypior Seite 14 Stand: 10.02.2007 Einführung in die Programmiersprache JAVA Listen Die mit der Datenstruktur Liste zusammenhängenden Objekte findet man im Package java.util. In Java gibt es zwei verschiedene Arten von Listen: • ArrayList • LinkedList ArrayList basiert auf einem normalen Datenfeld, während LinkedList Objekte miteinander verkettet, d.h., jedes Objekt hat Zeiger auf Vorgänger und Nachfolger. LikedList ist schnell beim Einfügen und Löschen, während ArrayList durch Angabe des betreffenden Indexes schnelle Einund Ausgaben ermöglicht. Die Listen-Objekte implementieren das Collection-Interface und stellen daher folgende Methoden bereit: Methode int size() boolean isEmpty() boolean contains(Object o) clear() Object[ ] toArray[ ] Beschreibung Liefert die Anzahl der Elemente der Datenstruktur zurück true, wenn keine Elemente vorhanden sind true, wenn das Element in der Datenstruktur vorhanden ist löscht alle Elemente Umwandlung in ein Feld Damit Containerklassen universell einsetzbar sind, operieren sie nur auf den Objekten der allgemeinen Object – Klasse, von der alle anderen Klassen in Java abgeleitet sind. Daher ist es in der Regel notwendig, Rückgabewerte von Containermethoden durch expizite Typumwandlung zurückzuverwandeln (siehe Beispiel unten). Für Listen (und auch für die Datenstrukturen Stack (Kellerspeicher), Hashset (Menge) und Hashtable (indizierte Tabellen)) steht das sogenannte Iterator-Konzept zur Verfügung. Ein Iterator erlaubt ein schnelles Durchlaufen der zugrunde liegenden Datenstruktur. Methode Iterator iterator() boolean hasNext() Object next() Beschreibung liefert einen Iterator für die Datenstruktur true, wenn noch weitere Elemente vorhanden sind das nächste Element liefern Beispiel 10: Erzeugen einer Liste und Ausgabe der Listeninhalte mit und ohne Iterator. // Datei CListe.java // Beispiel für eine Liste von Typ LinkedList import java.util.*; class CPerson { String Name; int Tel; Wypior Seite 15 Stand: 10.02.2007 Einführung in die Programmiersprache JAVA // der Konstruktor CPerson(String PName, int PTel) { Name = PName; Tel = PTel; } } public class CListe { public static void main(String []args) { // eine Liste anlegen und einige Namen ans // Ende einfügen LinkedList freunde = new LinkedList(); CPerson aktuell = new CPerson("Dirk",455689); freunde.add(aktuell); // ans Ende anhängen aktuell = new CPerson("Peter",543679); freunde.add(aktuell); // ans Ende anhängen // Objekt direkt erzeugen und anhängen freunde.add(new CPerson("Katja",238590)); // Objekt direkt erzeugen und vorne einfügen freunde.add(0,new CPerson("Julia",749326)); // den Inhalt der Liste ausgeben: per get-Funktion // und dann mit einem Iterator System.out.println("\nTelephonnummern ausgeben\n"); for(int i = 0; i < freunde.size(); i++) { aktuell = (CPerson) freunde.get(i); System.out.println(aktuell.Name + " " + aktuell.Tel); } //Iterator verwenden System.out.println("\nTelephonnummern ausgeben\n"); for(Iterator it = freunde.iterator(); it.hasNext(); ) { aktuell = (CPerson) it.next(); System.out.println(aktuell.Name + " " + aktuell.Tel); } } } Wypior Seite 16 Stand: 10.02.2007 Einführung in die Programmiersprache JAVA Fenster-Applikationen Der Teil von Java, mit dem man Programme mit grafischer Benutzeroberfläche (engl.: graphical user interface = GUI) erstellen kann, wird mit AWT (Abstact Window Toolkit) bezeichnet. Er besteht aus einer Sammlung von verschiedenen Klassen, die alle mit java.awt beginnen und Hunderte von Klassen und Methoden zur Verfügung stellen. Fenster-Applikationen beinhalten in der Regel AWT-Komponenten (Label, Textfelder, Button usw.). Die Nutzung dieser Komponenten führt zur Auslösung von Ereignissen (Events), die mit Hilfe von Event-Handlern behandelt werden können. Das zugrunde liegende Fenster-Objekt wird auch als Frame bezeichnet. Es beinhaltet nur Attribute (Eigenschaften) und Methoden, die zu seiner Darstellung dienlich sind. Eventhandler zum Schließen oder zum Verändern der Größe usw. müssen explizit hinzugefügt werden. Ebenso muß ein Container-Objekt vorgesehen werden, dass zur Aufnahme der weiteren Komponenten dient. Ereignisbehandlung Bei der Verarbeitung von Ereignissen unterscheidet das AWT Event-Quellen (Source) und Event-Lauscher (Listener). Die Event-Quellen sind die GUIKomponenten, die Event-Lauscher sind spezielle Klassen, die sich mit dem Abfangen und Bearbeiten der Ereignisse befassen. Der erste Schritt zur Ereignisbehandlung besteht darin, java.awt.event zu importieren. Will ein Programm ein bestimmtes Ereignis für eine bestimmte Komponente abfangen, muss es lediglich einen passenden EventLauscher definieren und diesen für die betreffende Komponente mit Hilfe entsprechender Methoden registrieren. In Java werden die Methoden zur Ereignisbehandlung in speziellen Listenerinterfaces vorgegeben. Eine Klasse, die ein Interface implementiert, muss alle Methoden, die in dem Interface deklariert sind, definieren und mit Code versehen. Immer dann, wenn dieser Umstand lästig ist, weil nicht alle Methoden benötigt werden, kann auf Adapter-Klassen ausgewichen werden. Wypior Seite 17 Stand: 10.02.2007 Einführung in die Programmiersprache JAVA Hierachie der Ereignisklassen: Hierachie der Event-Listener-Interfaces: Einige Adapterklassen: Listener Interface ActionListener FocusListener Adapter-Klasse keine FocusAdapter KeyListener KeyAdapter MouseListener MouseAdapter MouseMotionListener MouseMotionAdapter ItemListener TextListener WindowListener keine keine WindowAdapter Methoden actionPerformed(ActionEvent) focusGained(FocusEvent) focusLost(FocusEvent) keyPressed(KeyEvent) keyReleased(KeyEvent) keyTyped(KeyEvent) mouseClicked(MouseEvent) mouseEntered(MouseEvent) mouseExited(MouseEvent) mousePressed(MouseEvent) mouseDragged(MouseEvent) mouseMoved(MouseEvent) itemStateChanged(ItemEvent) textValueChanged(TextEvent) windowClosing(WindowEvent) windowActivated(WindowEvent) windowDeactivated(WindowEvent) windowIconified(WindowEvent) windowDeiconified(WindowEvent) Beispiel 11: Berechnung der Fakultät einer Zahl programmiert als Fenster-Applikation: 01 02 03 04 05 06 import java.awt.*; import java.awt.event.*; import javax.swing.*; /** * Wypior Seite 18 Stand: 03.02.2007 Einführung in die Programmiersprache JAVA 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 * Berechnung der Fakultät einer Zahl * * @version 1.0 vom 04.01.2007 * @author Hans Wypior */ public class Fakult extends JFrame { // Anfang Variablen private JLabel jLabel1 = new JLabel(); private JTextField teZahl = new JTextField(); private JLabel jLabel2 = new JLabel(); private JLabel jLabel3 = new JLabel(); private JTextField teErgebnis = new JTextField(); private JButton btRechne = new JButton(); // Ende Variablen public Fakult(String title) { // Frame-Initialisierung super(title); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent evt) { System.exit(0); } }); int frameWidth = 326; int frameHeight = 227; setSize(frameWidth, frameHeight); Container cp = getContentPane(); cp.setLayout(null); // Anfang Komponenten Wypior jLabel1.setBounds(88, 56, 31, 16); jLabel1.setText("Zahl"); jLabel1.setFont (new Font("MS Sans Serif", Font.BOLD, 13)); cp.add(jLabel1); teZahl.setBounds(128, 56, 81, 23); teZahl.setBackground(Color.WHITE); teZahl.setFont (new Font("Times New Roman", Font.PLAIN, 13)); teZahl.setText(""); cp.add(teZahl); jLabel2.setBounds(16, 16, 242, 16); jLabel2.setText("Berechnung der Fakultät einer Zahl"); jLabel2.setFont (new Font("MS Sans Serif", Font.BOLD, 13)); cp.add(jLabel2); jLabel3.setBounds(56, 88, 63, 16); jLabel3.setText("Ergebnis"); jLabel3.setFont (new Font("MS Sans Serif", Font.BOLD, 13)); cp.add(jLabel3); teErgebnis.setBounds(128, 88, 81, 24); teErgebnis.setBackground(Color.WHITE); teErgebnis.setText(""); cp.add(teErgebnis); btRechne.setBounds(128, 136, 83, 25); btRechne.setFont (new Font("MS Sans Serif", Font.BOLD, 13)); btRechne.setText("Los"); cp.add(btRechne); btRechne.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { btRechneActionPerformed(evt); } }); // Ende Komponenten Seite 19 Stand: 03.02.2007 Einführung in die Programmiersprache JAVA 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 } setResizable(false); setVisible(true); } // Anfang Ereignisprozeduren public void btRechneActionPerformed(ActionEvent evt) { int erg=1; int zahl = Integer.parseInt(teZahl.getText()); for (int i=1;i<=zahl;i++) { erg = erg*i; } teErgebnis.setText(String.valueOf(erg)); } // Ende Ereignisprozeduren public static void main(String[] args) { new Fakult("Fakultät"); } LayoutLayout-Manager Der Anspruch der Entwickler von Java, ihre Sprache Plattform-unabhängig und internetfähig zu gestalten erforderte eine Lösung hinsichtlich der grafischen Darstellung von Komponenten unter verschiedenen Betriebssystemen. Diese Lösung bietet der Layout-Manager. Unter Nutzung der setLayout()-Methode des zugrunde liegenden Containers werden die Komponenten mit seiner Hilfe angeordnet. Übersicht über die gebräuchlichsten Layout-Manager: Konstruktor Anordnung FlowLayout() BorderLayout() der Reihe nach in fünf Gebieten: Central, North, East, South, West GridLayout(n,m) gitterartig in n × m - Matrix Hinzufügen von Komponenten durch: add(Komponente) add("East",Komponente) add("Center",Komponente) usw. add(Komponente – 1) add(Komponente – 2) usw. Beispiel 12: Ein einfacher Taschenrechner mit den 4 Grundrechenarten: import java.awt.*; import java.awt.event.*; public class RechnerFrame extends Frame { Button btOk, btClr; TextField teZahl1; TextField teZahl2; TextField teErg; Wypior Seite 20 Stand: 03.02.2007 Einführung in die Programmiersprache JAVA Choice kbOperand; Panel Panel Panel Panel paButton; paEingabe; paAusgabe; paTemp; Double D1,D2,D3; class CWindowEventLauscher extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); } } //als innere Klasse def. public RechnerFrame() //Konstruktor { addWindowListener(new CWindowEventLauscher()); btOk = new Button("="); btClr = new Button("Clear"); kbOperand = new Choice(); kbOperand.addItem(" + "); kbOperand.addItem(" - "); kbOperand.addItem(" * "); kbOperand.addItem(" / "); teZahl1 = new TextField(); teZahl2 = new TextField(); teErg = new TextField(); teErg.setEditable(false); paButton = new Panel(); paButton.setLayout(new FlowLayout()); paButton.add(kbOperand); paButton.add(btOk); paButton.add(btClr); paEingabe = new Panel(); paEingabe.setLayout(new GridLayout(2,2)); paEingabe.add(new Label("Zahl 1 ")); paEingabe.add(teZahl1); paEingabe.add(new Label("Zahl 2 ")); paEingabe.add(teZahl2); paAusgabe = new Panel(); paAusgabe.setLayout(new GridLayout(1,2)); paAusgabe.add(new Label("Ergebnis ")); paAusgabe.add(teErg); paTemp = new Panel(); paTemp.setLayout(new BorderLayout()); paTemp.add("North",paButton); paTemp.add("South",paAusgabe); setLayout(new BorderLayout()); add("North",paEingabe); add("South",paTemp); } Wypior Seite 21 Stand: 03.02.2007 Einführung in die Programmiersprache JAVA public boolean action(Event e, Object o) //Methode überschreiben { if (e.target instanceof Button) { if("=".equals(o)) { D1 = new Double(teZahl1.getText()); D2 = new Double(teZahl2.getText()); switch(kbOperand.getSelectedIndex()) { case 0: D3 = new Double(D1.doubleValue()+D2.doubleValue()); break; case 1: D3 = new Double(D1.doubleValue()-D2.doubleValue()); break; case 2: D3 = new Double(D1.doubleValue()*D2.doubleValue()); break; case 3: D3 = new Double(D1.doubleValue()/D2.doubleValue()); break; default: D3 = new Double(0); } teErg.setText(Double.toString(D3.doubleValue())); repaint(); } else if("Clear".equals(o)) { teZahl1.setText(" "); teZahl2.setText(" "); teErg.setText(" "); repaint(); } return true; } return false; } public static void main(String[] args) { RechnerFrame Rechner = new RechnerFrame(); Rechner.pack(); Rechner.show(); } } Applets Besonderheiten Applet bedeutet soviel wie "little Application". Dies deutet schon an, was darunter zu verstehen ist: Applets sind keine selbständigen Programme, sondern benötigen immer eine bestimmte Umgebung, in der sie existieren und ablaufen können. Diese Umgebung stellt in der Regel ein wwwBrowser dar, wobei das Applet in HTML-Seiten eingebaut wird. Wypior Seite 22 Stand: 03.02.2007 Einführung in die Programmiersprache JAVA Applets besitzen weniger Rechte als Applikationen. Dateizugriffe sind nicht ohne Weiteres erlaubt, sondern erfordern digitale Signaturen. Ladezugriffe über das Internet sind nur auf dem Server zulässig, von dem das Applet geladen wurde. Applets werden von der AWT-Containerklasse java.applet.Applet, bzw. bei Verwendung von Swing von javax.swing.JApplet abgeleitet und als public deklariert. Statt der Eintrittsfunktion main() definiert man in einem Applet eine oder mehrere der folgenden Methoden, die automatisch aufgerufen werden: init(), start(), stop(), paint(), destroy() Beispiel 13: Einfaches Applet mit Grafik-Primitiven: import java.awt.*; import java.applet.*; public class GrafikApplet extends Applet { public void init() { setSize(650,300); } public void paint(Graphics g) { g.drawLine(20,30,610,30); g.drawRect(20,50,90,90); g.fillRect(120,50,90,90); g.drawRoundRect(20,150,90,90,10,20); //arcWidth = 10, arcHeight = 20 g.fillRoundRect(120,150,90,90,10,20); g.setColor(getBackground()); g.draw3DRect(220,50,90,90,true); g.draw3DRect(320,50,90,90,false); g.fill3DRect(420,50,90,90,true); g.fill3DRect(520,50,90,90,false); Color Blau = new Color(0,0,255); Color Rot = new Color(255,0,0); g.setColor(Blau); g.drawOval(220,150,90,90); g.setColor(Rot); g.fillOval(320,150,90,90); // RGB-Modell Color Gelb = new Color(0xffff00); g.setColor(Gelb); int xKoordinaten[] = {420,465,510,420}; int yKoordinaten[] = {240,150,240,240}; g.drawPolygon(xKoordinaten,yKoordinaten,4); g.fillPolygon(xKoordinaten,yKoordinaten,4); //Grafikprimitive als Instanzen von Klassen int x2Koordinaten[] = {520,565,610,520}; Polygon myPolygon = new Polygon(x2Koordinaten,yKoordinaten,4); g.setColor(defineColor()); g.fillPolygon(myPolygon); } public Color defineColor() Wypior Seite 23 Stand: 03.02.2007 Einführung in die Programmiersprache JAVA { int rot = (int) (Math.random()*255); int gruen = (int) (Math.random()*255); int blau = (int) (Math.random()*255); return new Color(blau,gruen,rot); } } Der Aufruf des Applets von einer HTML-Seite gestaltet sich wie folgt: <html> <head> <title>GrafikApplet-Applet</title> </head> <body> <h1>GrafikApplet-Applet</h1> <hr> <applet code="GrafikApplet.class" width="400" height="300"> </applet> <hr> </body> </html> Threads Aus dem Englischen übersetzt bedeutet der Begriff Thread Faden. Gemeint ist der "Faden", an dem Prozesse angehängt sind, die quasi gleichzeitig ablaufen, wobei jedem Prozess ein Zeitfenster zur Verfügung steht. Es handelt sich also um die Realisierung von Multitasking. Üblicherweise benutzt man zur Generierung von Threads das Interface "Runnable" Das nachfolgende Beispiel dient zur Demonstration, wie Threads von Programmen benutzt werden. Es kann problemlos zu einer Uhr mit Zeigern erweitert werden. Beispiel 14: Drehen eines Zeigers im Sekundentakt. import java.applet.*; import java.awt.*; import java.awt.event.*; /** * Rotation eines Zeigers * @version 1.0 vom 16.04.06 * @Hans Wypior */ public class CRotationLine extends Applet implements Runnable { private Button btzeichne; private Leinwand Malflaeche; private Panel pa1; private Panel pa2; private Label lb1; private Label lb2; Thread thread; boolean anhalten; Wypior Seite 24 Stand: 03.02.2007 Einführung in die Programmiersprache JAVA public void init() { setSize(400,400); btzeichne = new Button(); btzeichne.setLabel("Stop"); Malflaeche = new Leinwand(); pa1 = new Panel(); pa1.add(Malflaeche); //Malfläche auf Panel aufbringen pa2 = new Panel(); pa2.setLayout(new GridLayout(1,3,20,20)); lb1 = new Label(); lb2 = new Label(); pa2.add(lb1); pa2.add(btzeichne); pa2.add(lb2); setLayout(new FlowLayout()); add(pa1); add(pa2); btzeichne.addActionListener (new ActionListener() { public void actionPerformed(ActionEvent evt) { if (!anhalten) { stop(); btzeichne.setLabel("Start"); } else { start(); btzeichne.setLabel("Stop"); } } } ); } public void zeichneNeu(double alpha) { Malflaeche.Zeiger.drehen(alpha); Malflaeche.repaint(); } public void start() { if (thread == null) { anhalten = false; thread = new Thread(this); thread.start(); } } public void stop() { anhalten = true; thread.interrupt(); thread = null; } Wypior Seite 25 Stand: 03.02.2007 Einführung in die Programmiersprache JAVA public void run() { while (!anhalten) { zeichneNeu(6); try { thread.sleep(1000); } catch(InterruptedException e) { ; } //thread = null; } } } // ------------------------------ Leinwand - Objekt ------------------------class OptDBCanvas extends Canvas //optimiertes Double-Buffering { public void update (Graphics g) { Graphics bg; Image buffer = null; Rectangle r = g.getClipBounds(); buffer = createImage(r.width, r.height); bg = buffer.getGraphics(); bg.setColor(getBackground()); bg.fillRect(0,0,r.width,r.height); bg.setColor(getForeground()); bg.translate(-r.x, -r.y); paint(bg); g.drawImage(buffer,r.x,r.y,this); } } class Leinwand extends OptDBCanvas { public Color Farbe; public CLine Zeiger; int b; int h; Leinwand() { setBackground(Color.BLUE); setForeground(Color.yellow); Farbe = Color.white; Zeiger = new CLine(0,0,0,-100,Color.white); } public void paint(Graphics g) { g.setColor(Farbe); g.translate(160,160); g.drawOval(-100,-100,200,200); Zeiger.zeichne(g); } Wypior Seite 26 Stand: 03.02.2007 Einführung in die Programmiersprache JAVA public void setColor() { setBackground(Color.BLUE); setForeground(Color.yellow); Farbe = Color.white; } public Dimension getMinimumSize() { return new Dimension(320,320); } public Dimension getPreferredSize() { return getMinimumSize(); } } //Ende Leinwand // ------------------------------- CVektor - Objekt ------------------------class CLine { private CPunkt P[] = new CPunkt[2]; Color Farbe; CLine(int ax, int ay, int bx, int by, Color Farbwert) { Farbe = Farbwert; P[0] = new CPunkt(ax,ay,Farbwert); //Vektoranfang (Drehpunkt) P[1] = new CPunkt(bx,by,Farbwert); //Vektorende } public void drehen(double alpha) { P[1].drehen(alpha); } public void zeichne(Graphics g) { g.setColor(Farbe); g.drawLine((int)P[0].x,(int)P[0].y,(int)P[1].x,(int)P[1].y); } } // -------------------------------- Punkt - Objekt -------------------------class CPunkt { double x,y; int radius; Color Farbe; //Weltkoordinaten //Pixelradius CPunkt(double wx, double wy, Color Farbwert) { x = wx; y = wy; radius = 5; Farbe = Farbwert; } Wypior Seite 27 Stand: 03.02.2007 Einführung in die Programmiersprache JAVA public void zeichne(Graphics g) { g.setColor(Farbe); g.fillOval((int)x,(int)y,radius,radius); } public void drehen(double alpha) { double Bogen; double x1,y1; Bogen = Math.toRadians(alpha); x1=x; y1=y; x=x1*Math.cos(Bogen)-y1*Math.sin(Bogen); y=x1*Math.sin(Bogen)+y1*Math.cos(Bogen); } //Bogenmaß } Nützliches und Wissenswertes Drucken Um in Java einen drucken zu können, muss bei einer Klasse das Interface "Printable" eingebunden werden, das im Paket java.awt.print enthalten ist. Im nachfolgenden Beispiel wird der Inhalt des Panels nach Druck auf den entsprechenden Button auf einem Drucker ausgegeben. Beispiel 15: Einbinden und Benutzen eines Druckers import import import import java.awt.*; java.awt.event.*; javax.swing.*; java.awt.print.*; /** * * Drucken eines Panelinhalts * * @version 1.0 vom 24.01.2007 * @author Hans Wypior Wypior Seite 28 Stand: 03.02.2007 Einführung in die Programmiersprache JAVA */ public class Drucktest extends JFrame { private CMalPanel jPanel1 = new CMalPanel(); private JButton btDruck = new JButton(); public Drucktest(String title) //Konstruktor { super(title); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent evt) { System.exit(0); } }); int frameWidth = 400; int frameHeight = 250; setSize(frameWidth, frameHeight); //Das Toolkit-Objekt ermittelt Hardware-Eigenschaften des Betriebsystems Dimension d = Toolkit.getDefaultToolkit().getScreenSize(); //Fenster mittig positionieren int x = (d.width - getSize().width) / 2; int y = (d.height - getSize().height) / 2 ; setLocation(x, y); jPanel1.setBackground(Color.WHITE); jPanel1.setForeground(Color.BLACK); getContentPane().add(jPanel1,BorderLayout.CENTER); btDruck.setText("Drucken"); getContentPane().add(btDruck,BorderLayout.SOUTH); btDruck.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { btDruckActionPerformed(evt); } }); setResizable(false); show(); } public void btDruckActionPerformed(ActionEvent evt) { DatenDrucken(); } public void DatenDrucken() { // Druckauftrag erzeugen PrinterJob Drucker = PrinterJob.getPrinterJob(); //nicht 'new' verwenden! // Panelinhalt als Druckvorlage benutzen Drucker.setPrintable(jPanel1); PageFormat Seitenformat = Drucker.pageDialog(Drucker.defaultPage()); try { // Druckauftrag starten Drucker.print(); } catch (Exception PrintException) { /* System.out.println("Fehler beim Drucken!"); */ } Wypior Seite 29 Stand: 03.02.2007 Einführung in die Programmiersprache JAVA } public static void main(String[] args) { new Drucktest("Drucktest"); } } /*------------------------------- CMalPanel ----------------------------- */ class CMalPanel extends JPanel implements Printable { CMalPanel() { super(); } public void paint(Graphics g) { g.setColor(Color.white); g.fillRect(0,0,getSize().width,getSize().height); g.setColor(Color.blue); g.setFont(new Font("Arial",Font.BOLD,20)); g.drawString("JAVA-Fortbildung",120,70); g.drawString("Lloyd Gymnasium Bremerhaven",50,120); } public int print(Graphics g, PageFormat pageFormat, int pageIndex) { // nur eine Seite drucken if (pageIndex == 0) { // Ursprung auf Ausdruck verschieben g.translate(100, 100); // Seite zeichnen paint(g); // eine Seite gedruckt return Printable.PAGE_EXISTS; } // keine Seite gedruckt return Printable.NO_SUCH_PAGE; } } Grafik Java bietet zum Erstellen von und Arbeiten mit Grafik umfangreiche Unterstützung in Form von Bibliotheken. So gehört die Java2D-Bibliothek zum Lieferumfang beim Download vom SunServer. Ebenfalls erhältlich sind Bibliotheken für 3D-Grafik, wobei man vorher entscheiden muss, ob die 3D-Grafik vom OPENGL- oder vom DIRECTX-Standard abgeleitet werden soll. Während der Befehlsumfang von 2D-Grafik relativ übersichtlich ist und problemlos wie "normale" Grafik eingesetzt werden kann, stellt die Nutzung von 3D-Grafik den Programmierer vor die Aufgabe, sich mit Szenegraphen auseinanderzusetzen. Dass es möglich ist, auch mit elementaren Mitteln 3D-Grafik zu betreiben, soll das nachfolgende Programm in Beispiel 16 demonstrieren. Wypior Seite 30 Stand: 03.02.2007 Einführung in die Programmiersprache JAVA Beispiel 16: Drehende Dreiecke import java.applet.*; import java.awt.*; import java.awt.event.*; /** * Drehendes Dreieck mit unterschiedlichem Zoom * @version 1.1 vom 16.04.06 * @Hans Wypior */ public class CAnimDreieck extends Applet implements Runnable { private Button btzeichne; private Leinwand Malflaeche; private Panel pa1; private Panel pa2; Wypior Seite 31 Stand: 03.02.2007 Einführung in die Programmiersprache JAVA private Label lb1; private Label lb2; Thread thread; boolean anhalten; public void init() { setSize(400,400); btzeichne = new Button(); btzeichne.setLabel("Stop"); Malflaeche = new Leinwand(); pa1 = new Panel(); pa1.add(Malflaeche); pa2 = new Panel(); pa2.setLayout(new GridLayout(3,1,20,20)); lb1 = new Label(); lb2 = new Label(); pa2.add(lb1); pa2.add(btzeichne); pa2.add(lb2); setLayout(new FlowLayout()); add(pa1); add(pa2); btzeichne.addActionListener (new ActionListener() { public void actionPerformed(ActionEvent evt) { if (!anhalten) { stop(); btzeichne.setLabel("Start"); } else { start(); btzeichne.setLabel("Stop"); } } } ); } public void zeichneNeu(double alpha) { Malflaeche.s.drehen('y',alpha); Malflaeche.repaint(); } public void start() { if (thread == null) { anhalten = false; thread = new Thread(this); thread.start(); } } public void stop() { anhalten = true; Wypior Seite 32 Stand: 03.02.2007 Einführung in die Programmiersprache JAVA thread.interrupt(); thread = null; } public void run() { while (!anhalten) { zeichneNeu(5); try { thread.sleep(50); } catch(InterruptedException e) { ; } //thread = null; } } // ---------------------------- Leinwand - Objekt -------------------------class DoubleBufferCanvas extends Canvas { public void update (Graphics g) { Graphics bg; Image buffer = null; Dimension d = size(); buffer = createImage(d.width, d.height); bg = buffer.getGraphics(); bg.setColor(getBackground()); bg.fillRect(0,0,d.width,d.height); bg.setColor(getForeground()); paint(bg); g.drawImage(buffer,0,0,this); } } //Double-Buffering class OptDBCanvas extends Canvas //optimiertes Double-Buffering { public void update (Graphics g) { Graphics bg; Image buffer = null; Rectangle r = g.getClipBounds(); buffer = createImage(r.width, r.height); bg = buffer.getGraphics(); bg.setColor(getBackground()); bg.fillRect(0,0,r.width,r.height); bg.setColor(getForeground()); bg.translate(-r.x, -r.y); paint(bg); g.drawImage(buffer,r.x,r.y,this); } } class Leinwand extends OptDBCanvas { public Color Farbe; public CDreieck s = new CDreieck(); Wypior Seite 33 Stand: 03.02.2007 Einführung in die Programmiersprache JAVA private private private private WinView WinView WinView WinView WV1; WV2; WV3; WV4; Leinwand() { setBackground(Color.BLUE); setForeground(Color.yellow); Farbe = Color.white; WV1 = new WinView(-80,-80,-50,80,80,50,5,5,5,155,155,-5); WV2 = new WinView(-50,-50,-50,50,50,50,165,5,5,315,155,-5); WV3 = new WinView(-20,-20,-50,20,20,50,5,170,5,155,310,-5); WV4 = new WinView(-12,-12,-50,12,12,50,165,170,5,315,310,-5); } public void paint(Graphics g) { g.setColor(Farbe); WV1.showViewport(g); s.zeichne(g,WV1); WV2.showViewport(g); s.zeichne(g,WV2); WV3.showViewport(g); s.zeichne(g,WV3); WV4.showViewport(g); s.zeichne(g,WV4); } public void setColor() { int rot = (int) (Math.random()*255); int gruen = (int) (Math.random()*255); int blau = (int) (Math.random()*255); Farbe = new Color(blau,gruen,rot); } public Dimension getMinimumSize() { return new Dimension(320,320); } public Dimension getPreferredSize() { return getMinimumSize(); } } //Ende Leinwand // ----------------------------- CVektor - Objekt -------------------------public class CDreieck { private CPunkt P[] = new CPunkt[4]; private Polygon DEck = new Polygon(); CDreieck() { P[0] = new CPunkt(-10,-5,0,Color.yellow); P[1] = new CPunkt(10,-5,0,Color.white); P[2] = new CPunkt(0,5,0,Color.green); Wypior Seite 34 //Vektoranfang //Vektorende //Hilfspunkte der Spitze Stand: 03.02.2007 Einführung in die Programmiersprache JAVA } public void drehen(char achse, double alpha) { for(int i=0; i<3; i++) { P[i].drehen(achse,alpha); } } public void zeichne(Graphics g, WinView vw) { g.setColor(Color.yellow); for (int i=0; i<3; i++) { P[i].Bild(vw); DEck.addPoint(P[i].bx,P[i].by); } g.fillPolygon(DEck); DEck.reset(); //g.drawLine(P[0].bx,P[0].by,P[1].bx,P[1].by); //g.drawLine(P[1].bx,P[1].by,P[2].bx,P[2].by); //g.drawLine(P[2].bx,P[2].by,P[0].bx,P[0].by); } } // -------------------------------- Punkt - Objekt -------------------------private class CPunkt { double x,y,z; int bx,by,bz; int radius; Color Farbe; //Weltkoordinaten //Bildkoordinaten //Pixelradius CPunkt() { x = 0; y = 0; z = 0; radius = 5; Farbe = Color.white; } CPunkt(double wx,double wy,double wz) { x = wx; y = wy; z = wz; radius = 5; Farbe = Color.white; } CPunkt(double wx,double wy,double wz, Color color) { x = wx; y = wy; z = wz; radius = 5; Farbe = color; } public void neu(double nx,double ny,double nz) { x = nx; y = ny; z = nz; Wypior Seite 35 Stand: 03.02.2007 Einführung in die Programmiersprache JAVA } public void Bild(WinView vw) { vw.Bild(this,0); } //orthogonal public void zeichne(Graphics g, WinView vw) { Bild(vw); g.setColor(Farbe); g.fillOval(bx,by,radius,radius); } public void move(double tx,double ty,double tz) { x = x+tx; y = y+ty; z = z+tz; } public void drehen(char achse, double alpha) { double Bogen; double x1,y1,z1; Bogen = Math.toRadians(alpha); x1=x; y1=y; z1=z; switch (achse) { case 'x': y=y1*Math.cos(Bogen)-z1*Math.sin(Bogen); z=y1*Math.sin(Bogen)+z1*Math.cos(Bogen); break; case 'y': x=x1*Math.cos(Bogen)+z1*Math.sin(Bogen); z=-x1*Math.sin(Bogen)+z1*Math.cos(Bogen); break; case 'z': x=x1*Math.cos(Bogen)-y1*Math.sin(Bogen); y=x1*Math.sin(Bogen)+y1*Math.cos(Bogen); break; } } //Translationsvektor //Bogenmaß } // -------------------- Window - Viewport - Objekt ------------------------ private class WinView { private CPunkt WO; private CPunkt WU; private CPunkt VO; private CPunkt VU; private double a; private double b; private double Abstand; // // // // // Window-Eckpunkt oben links Window-Eckpunkt unten rechts Viewport-Eckpunkt oben links Viewport-Eckpunkt unten rechts Parameter für Schrägprojektion // Kameraposition auf der z-Achse WinView() { WO = new CPunkt(-1000,-1000,-1000); WU = new CPunkt(1000,1000,1000); Wypior Seite 36 Stand: 03.02.2007 Einführung in die Programmiersprache JAVA VO = new CPunkt(0,0,0); VU = new CPunkt(200,200,100); Abstand = 2000; a = Math.toRadians(Math.sin(120)); b = Math.toRadians(Math.cos(120)); } WinView(double wox, double woy, double double wux, double wuy, double double vox, double voy, double double vux, double vuy, double { WO = new CPunkt(wox,woy,woz); WU = new CPunkt(wux,wuy,wuz); VO = new CPunkt(vox,voy,voz); VU = new CPunkt(vux,vuy,vuz); Abstand = 2000; a = Math.toRadians(Math.sin(120)); b = Math.toRadians(Math.cos(120)); } woz, wuz, voz, vuz) //Window links oben //Window rechts unten //Viewport links oben //Viewport rechts unten public void changeWindow(CPunkt oben, CPunkt unten) { WO.neu(oben.x,oben.y,oben.z); WU.neu(unten.x,unten.y,unten.z); } public void changeViewport(CPunkt oben, CPunkt unten) { VO.neu(oben.x,oben.y,oben.z); VU.neu(unten.x,unten.y,unten.z); } public void Bild(CPunkt WP, int PArt) { double bx,by,bz; double vx,vy,vz; switch (PArt) { case 0: // Zentral double d = Abstand; bx = d/(d-WP.z)*WP.x; by = d/(d-WP.z)*WP.y; bz = WP.z; break; case 1: bx = WP.x+a*WP.z; by = WP.y+b*WP.z; bz = WP.z; break; default: bx = WP.x; by = WP.y; bz = WP.z; break; // Orthogonal } vx = (bx - WU.x)*((VO.x-VU.x)/(WO.x-WU.x))+VU.x; vy = (by - WU.y)*((VO.y-VU.y)/(WO.y-WU.y))+VU.y; vz = (bz - WU.z)*((VO.z-VU.z)/(WO.z-WU.z))+VU.z; WP.bx = (int) vx; Wypior Seite 37 Stand: 03.02.2007 Einführung in die Programmiersprache JAVA WP.by = (int) vy; WP.bz = (int) vz; } public void showViewport(Graphics g) { g.drawRect((int) VO.x,(int) VO.y,(int)(VU.x-VO.x),(int)(VU.y-VO.y)); } } } 2D - Grafik 2D-Grafikbefehle sowie der Gebrauch des Media-Trackers werden im folgenden Beispiel gezeigt. Beispiel 18: Erzeugen eines Textes mit dem "Feeling von Word-Art". (Quelle: Data Becker) /** * 2D-Grafik Text * Quelle: Data */ import import import import import import java.awt.*; java.awt.geom.*; java.awt.event.*; java.awt.image.*; java.awt.font.*; javax.swing.*; public class Textdemo extends JPanel { Image img; String imagefile = "nym.jpg"; String text = new String("Nymphenburg"); public Textdemo() { setBackground(Color.white); // Bild laden img = getToolkit().getImage(imagefile); // MediaTracker erzeugen MediaTracker mt = new MediaTracker(this); // MediaTracker mit Bild verknuepfen mt.addImage(img, 0); try { //Warten, bis das Image vollständig geladen ist, mt.waitForAll(); } catch (InterruptedException e) { /* mache nichts */ } } Wypior Seite 38 Stand: 03.02.2007 Einführung in die Programmiersprache JAVA public void paintComponent (Graphics g) { // paintComponent von JLabel aufrufen super.paintComponent(g); // 2D-Objekt erzeugen Graphics2D g2 = (Graphics2D) g; // Breite, Hoehe int w = getSize().width; int h = getSize().height; // Algorithmus fuer das Rendering g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); // Renderer fuer den Font FontRenderContext frc = g2.getFontRenderContext(); // Font Font font = new Font("Helvetica", 1, w/10); // Textlayout: Text, Font, FontRenderer TextLayout textTl = new TextLayout(text, font, frc); // Umrisslinie Shape outline = textTl.getOutline(null); // Rechteckbereich Rectangle r = outline.getBounds(); // Koordinaten transformieren AffineTransform transform = g2.getTransform(); transform.translate(w/2-(r.width/2), h/2+(r.height/2)); g2.transform(transform); // Farbe fuer den Umriss g2.setColor(Color.red); g2.draw(outline); // Zeichenbereich auf Font-Elemente beschraenken g2.setClip(outline); // Bild zeichnen g2.drawImage(img, r.x, r.y, r.width, r.height, this); } public static void main(String[] args) { // Fenster erzeugen JFrame f = new JFrame(); f.addWindowListener( new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } Wypior Seite 39 Stand: 03.02.2007 Einführung in die Programmiersprache JAVA }); // Fenstertitel f.setTitle("Textdemo.java"); // Bild hinzufuegen f.getContentPane().add(new Textdemo(),BorderLayout.CENTER); // Fenster anzeigen f.setSize(700,200); f.setVisible(true); } } Wypior Seite 40 Stand: 03.02.2007 Einführung in die Programmiersprache JAVA Quellen lfd Nr. 1 2 3 4 5 6 7 1 2 3 4 Wypior Titel Jetzt lerne ich Java Internet-Programmierung mit Java Grundkurs Java Objektorientierte Programmierung in Java Objektorientierte Programmierung in Java Java Handbuch der Java-Programmierung Verlag Markt + Technik Data Becker Vieweg Vieweg bhv Hanser Addison-Wesley ISBN 3-8272-6293-7 3-8158-2086-3 3-528-05711-4 3-528-05721-1 3-8266-7025-6 3-446-18854-1 3-8273-2201-4 Internetadressen http://www.javabuch.de http://lernen.bildung.hessen.de/informatik/javaeditor/index.htm http://www.crazy-team.net/ http://www.onlinetutorials.de/jav-003.htm Seite 41 Stand: 03.02.2007