Grafikprogrammierung in Java:
Grundlagen
11.1 Grundlagen
11.2 Grafische Grundelemente 11.3 Fensterklassen
11.4 Ereignisse und Widgets 11.5 Applets
11.6 Die Swing-Klassen
Schnittstellen für Anwenderprogramme
• Eine Schnittstelle für Anwenderprogramme (application programming interface, API) stellt wohldefinierte und standardisierte Klassen und Methoden zur
Verfügung, die von Anwenderprogrammen genutzt werden können.
• APIs ermöglichen es, vorhandene Software um weitere Funktionen zu ergänzen.
• Java stellt beispielsweise APIs für die folgenden Zwecke zur Verfügung:
◦ Grafikprogrammierung (mit AWT, Swing)
◦ Datenbankzugriffe (mit JDBC)
◦ Netzwerkprogrammierung
◦ Verarbeitung, Auswertung und Transformation von XML-Dokumenten
◦ Verschlüsselung von Daten (Sicherheit, Kryptografie, SecurityManager)
◦ Sound
◦ . . .
Grafikprogrammierung
Java bietet den Programmierern zwei Bibliotheken zur Programmierung von grafischen Benutzeroberflächen (graphical user interface, GUI) an:
• Abstract Window Toolkit (AWT)
Das AWT ermöglicht die Ausführung grundlegender grafischer Operationen. Die Klassen und Methoden des AWTs sind im Standardpaket java.awt enthalten.
• Swing
Seit der Version 1.1 gibt es eine zweite Grafikbibliothek im Java Development Kit.
Sie heißt Swing und ist Bestandteil des Erweiterungspakets javax.swing. Diese Bibliothek beseitigt etliche Schwächen des AWTs und bietet eine weitgehend
plattformunabhängige Schnittstelle. Die Möglichkeiten, die Swing bietet, übersteigen die des AWTs.
Grafikprogrammierung
Neben AWT und Swing gibt es eine verbreitete Bibliothek zur Programmierung grafischer Benutzeroberflächen:
• Standard Widget Toolkit (SWT)
SWT ist eine Bibliothek für die Erstellung grafischer Oberflächen mit Java. Sie wurde im Jahr 2001 von IBM für die Entwicklungsumgebung Eclipse entwickelt und kommt in einer ganzen Reihe von Anwendungen zum Einsatz, beispielsweise Eclipse selbst. SWT leidet auf einigen Nicht-Windows-Plattformen unter
Effizienzproblemen. SWT gehört nicht zum JDK.
Wir gehen hier (aus Zeitgründen) nicht auf SWT ein. Es gibt weitere Bibliotheken.
Das Abstract Window Toolkit
Die Fähigkeiten des AWTs lassen sich in vier Gruppen einteilen:
• Grundoperationen zum Zeichnen von Linien und Flächen und zur Ausgabe von Text
• Methoden zur Programmsteuerung durch die Behandlung von Maus-, Tastatur- und Fensterereignissen
• Dialogelemente zur Kommunikation mit dem Anwender
• Fortgeschrittene Operationen zur Ausgabe von Bitmaps und Tönen
Ein einführendes Beispiel
import java.awt.*;
public class Fenster extends Frame { Fenster() {
setBackground(Color.yellow);
setSize(200,150);
setLocation(500,500);
setVisible(true);
}
public static void main(String[] args) { new Fenster();
}
Das Abstract Window Toolkit
• Zum Ableiten einer eigenen Fensterklasse wird in der Regel entweder die Klasse Frame oder die Klasse Dialog verwendet.
• Um ein neues Fenster zu erhalten, muss ein Objekt der Klasse Frame erzeugt, auf die gewünschte Größe gebracht und durch Aufruf der Methode setVisible
sichtbar gemacht werden.
• Die Ausgabe in ein Fenster erfolgt durch Überlagern der Methode paint. Diese Methode wird immer dann aufgerufen, wenn das Fenster neu gezeichnet werden muss, z. B. beim Programmstart oder beim Verändern der Größe.
• Die Methode void paint(Graphics g) erhält als Parameter einen grafischen Kontext. Hierunter versteht man allgemeine Einstellungen für Schrift und Grafik,
Ein einführendes Beispiel
import java.awt.*;
class Rechteck extends Canvas { public void paint(Graphics g) {
g.setColor(Color.red);
g.fillRect(20,20,100,40);
g.setColor(Color.black);
g.drawString("Ein rotes Rechteck",20,80);
setLocation(20,15);
} }
// Vokabeltest: canvas = Leinwand
class EinfachesFenster extends Frame { EinfachesFenster() {
add(new Rechteck());
setBackground(Color.yellow);
setSize(200,150);
setVisible(true);
setLocation(200,200);
}
public static void main(String[] args) { new EinfachesFenster();
} }
Ereignisgesteuerte Programmierung
• Die Programme, die wir bisher betrachtet haben, arbeiten nach dem Prinzip der Ein-Ausgabe-Programmierung.
• Dieses Modell wird jetzt zur ereignisgesteuerten Programmierung erweitert.
Ereignisse sind beispielsweise das Drücken einer Taste, die Betätigung des Rollbalkens oder die Bewegung der Maus.
• Es gibt viele Varianten der ereignisgesteuerten Programmierung. In Java wird das sogenannte Delegation Based Event Handling verwendet. Es bietet die Möglichkeit, GUI-Ereignisse an beliebige Objekte weiterzuleiten und dort zu behandeln. Auf
diese Weise können die Oberfläche und die eigentliche Anwendung klar voneinander getrennt werden.
Ereignisgesteuerte Programmierung
• Jedes Ereignis besitzt eine Quelle (Source). Ein Ereignis kann von Beobachtern (Listener) wahrgenommen werden. Die Anmeldung von Beobachtern zur
Benachrichtigung vom Eintreten eines Ereignisses ist frei programmierbar und muss immer explizit erfolgen.
• Es ist nicht festgelegt, in welcher Reihenfolge die Beobachter vom Eintreten eines Ereignisses informiert werden. Sichergestellt ist lediglich, dass jeder Beobachter eine Kopie des ursprünglichen Ereignisses erhält.
• Bei der Verbreitung von Ereignissen ist zwischen den Modi single-cast und
multi-cast zu unterscheiden. Für Single-Cast-Ereignisse wird der Beobachter mit einer setxxListener-Methode gesetzt, für Multi-Cast-Ereignisse wird ein
Beobachter mit einer addxxListener-Methode der Menge der Beobachter
Beispiel: Schließen eines Fensters
• Um ein Fenster zu schließen, muss ein WindowListener registriert werden.
• Hierbei handelt es sich um einen Beobachter, dessen Methode windowClosing aufgerufen wird, wenn der Anwender das Fenster über ein System-Menü oder einen Button schließen möchte.
• Das Fenster wird durch setVisible(false) unsichtbar gemacht, seine Ressourcen durch dispose() wieder freigegeben.
Beispiel: Schließen eines Fensters
import java.awt.*;
import java.awt.event.*;
public class WindowClosingAdapter extends WindowAdapter { public void windowClosing(WindowEvent event) {
event.getWindow().setVisible(false);
event.getWindow().dispose();
System.out.println("Das Fenster wurde geschlossen!");
} }
Frame wnd = new Frame();
wnd.addWindowListener(new WindowClosingAdapter());
wnd.setSize(400,300);
wnd.setVisible(true);
Adapter-Klassen
• Eine Adapter-Klasse ist eine Klasse, die eine gegebene Schnittstelle implementiert, indem sie jede abstrakte Methode durch einen leeren Rumpf realisiert.
• Adapter-Klassen werden verwendet, wenn von einer Schnittstelle lediglich ein Teil der Methoden benötigt wird, der Rest aber uninteressant ist. In diesem Fall leitet man eine neue Klasse aus der Adapter-Klasse ab und überlagert nur die
erforderlichen Methoden.
• Beispiel: Die Klasse WindowAdapter implementiert die Schnittstellen
WindowListener, WindowStateListener und WindowFocusListener durch leere Rümpfe. Hierbei handelt es sich um die folgenden Methoden:
Die Klasse WindowAdapter
void windowActivated(WindowEvent e) void windowClosed(WindowEvent e) void windowClosing(WindowEvent e)
void windowDeactivated(WindowEvent e) void windowDeiconified(WindowEvent e) void windowGainedFocus(WindowEvent e) void windowIconified(WindowEvent e) void windowLostFocus(WindowEvent e) void windowOpened(WindowEvent e)
void windowStateChanged(WindowEvent e)
Ein einführendes Beispiel
Wir fassen zusammen:
import java.awt.*;
import java.awt.event.*;
class WindowClosingAdapter extends WindowAdapter { public void windowClosing(WindowEvent event) {
event.getWindow().setVisible(false);
event.getWindow().dispose();
System.out.println("Das Fenster wurde geschlossen!");
} }
class Rechteck extends Canvas { public void paint(Graphics g) {
g.setColor(Color.red);
g.fillRect(20,20,100,40);
g.setColor(Color.black);
g.drawString("Ein rotes Rechteck",20,80);
setLocation(20,15);
} }
public class EinfachesFenster extends Frame { EinfachesFenster(String title) {
super(title);
addWindowListener(new WindowClosingAdapter());
setBackground(Color.yellow);
setSize(400,200);
add(new Rechteck());
setVisible(true);
} }
EinfachesFenster e1 = new EinfachesFenster("Erstes Fenster"), e2 = new EinfachesFenster("Zweites Fenster"), e3 = new EinfachesFenster("Drittes Fenster");
e1.setLocation(200,200);
e2.setLocation(400,300);
e3.setLocation(600,400);
Grafikprogrammierung in Java:
Grafische Grundelemente
11.1 Grundlagen
11.2 Grafische Grundelemente 11.3 Fensterklassen
11.4 Ereignisse und Widgets 11.5 Applets
11.6 Die Swing-Klassen
Das grafische Koordinatensystem
• Die Ausgabe von grafischen Objekten basiert auf einem zweidimensionalen Koordinatensystem, dessen Ursprung (0,0) in der linken oberen Ecke liegt.
-
?
x
y
• Positive x-Werte erstrecken sich nach rechts, positive y-Werte nach unten. Die Maßeinheit entspricht einem Bildschirmpixel und ist somit geräteabhängig.
Der Benutzerbereich
• Es steht nicht das gesamte Fenster für Ausgaben zur Verfügung. Oben, unten, links und rechts wird Platz zur Ausgabe von Rahmen und Titelzeile benötigt.
• Mit
◦ getSize().width und getSize().height
kann die Gesamtbreite bzw. -höhe eines Fensters ermittelt werden. Durch
◦ getInsets().left, getInsets().right, getInsets().top und getInsets().bottom
lässt sich die Abmessung des Rahmens und durch Differenzbildung die des Benutzerbereichs (client area) bestimmen.
Elementare Grafikroutinen (Auswahl)
• void drawString(String s, int x, int y)
drawString schreibt den String s an die Position (x,y). Diese Koordinaten stellen das linke Ende der Basislinie von s dar.
• void drawChars(char[] c, int offset, int length, int x, int y) Diese Methode schreibt ein Zeichenfeld. Die Parameter offset und length
können zur Angabe des ersten Zeichens und der Anzahl der auszugebenden Zeichen verwendet werden.
Elementare Grafikroutinen (Auswahl)
Beispiel: Die Anweisungen
char[] c = {’a’,’b’,’c’,’d’,’e’,’f’};
g.drawString("Zeichenkette",50,50);
g.drawChars(c,1,4,50,150);
schreiben den String "Zeichenkette" an die Position (50,50) und darunter die Zeichen
"bcde" an die Position (50,150).
Elementare Grafikroutinen (Auswahl)
• void drawLine(int x1, int y1, int x2, int y2)
Diese Methode zieht eine Linie von der Position (x1,y1) zur Position (x2,y2).
• void drawRect(int x, int y, int width, int height)
drawRect zeichnet ein Rechteck der Breite width und der Höhe height, dessen linke obere Ecke an der Position (x,y) liegt.
• void drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight)
Es wird ein Rechteck mit abgerundeten Ecken gezeichnet. arcWidth und
arcHeight bestimmen die Halbachsen der Ellipse, die zur Darstellung der Ecken verwendet wird.
Elementare Grafikroutinen (Auswahl)
• void drawPolygon(int[] x, int[] y, int anzahl)
Diese Methode zeichnet einen Linienzug. Die x-Koordinaten der Punkte werden dem ersten Parameter, die y-Koordinaten dem zweiten Parameter entnommen. Die Anzahl der Koordinatenpaare wird durch den dritten Parameter festgelegt. Der Polygonzug wird geschlossen. Durch drawPolyline kann ein nichtgeschlossener Linienzug dargestellt werden.
Eine andere Möglichkeit, ein Polygon zu erzeugen, besteht darin, einen Konstruktor der Klasse Polygon aufzurufen:
• Polygon(int[] x, int[] y, int anzahl) Polygon()
Durch addPoint kann ein Polygon erweitert werden.
Elementare Grafikroutinen (Auswahl)
• void drawOval(int x, int y, int width, int height)
Mit dieser Methode können Kreise und Ellipsen gezeichnet werden. Die Parameter spezifizieren ein Rechteck wie in der Methode drawRect. Es wird die größte
Ellipse gezeichnet, die in dieses Rechteck hineinpasst.
• void drawArc(int x, int y, int width, int height, int startAngle, int arcAngle)
Mit drawArc kann ein Kreisbogen dargestellt werden. Die ersten vier Parameter geben den Kreis, startAngle den Anfangswinkel und arcAngle den Winkel an.
Elementare Grafikroutinen (Auswahl)
Die folgenden Funktionen stellen die gleichen geometrischen Objekte dar wie die obigen, zeichnen aber nicht nur deren Umrisse, sondern füllen auch ihre Fläche aus.
• void fillRect( ... )
• void fillRoundRect( ... )
• void fillPolygon( ... )
• void fillOval( ... )
• void fillArc( ... )
Elementare Grafikroutinen (Auswahl)
• void clearRect(int x, int y, int width, int height)
Die Methode clearRect überschreibt das angegebene Rechteck mit der aktuellen Hintergrundfarbe.
• void copyArea(int x, int y, int width, int height, int dx, int dy)
copyArea kopiert das ausgewählte Rechteck an die Position (x + dx, y + dy).
• Mit einer Clipping-Region kann die Ausgabe auf einen bestimmten Bereich eingeschränkt werden.
Schriftarten
• Ohne zusätzliche Anweisungen wird Text in einem systemabhängigen Standard-Font ausgegeben. Um einen anderen Font zur Textausgabe zu
verwenden, muss zuerst ein Font-Objekt erzeugt und dann in den Grafik-Kontext eingetragen werden.
• Ein Font-Objekt kann mit einem Konstruktor der Klasse Font erzeugt werden:
Font(String name, int style, int size)
• Mit
void setFont(Font font) und Font getFont()
kann der Font gesetzt bzw. abgefragt werden.
Schriftarten
• Der Parameter name gibt den Namen der gewünschten Schrift an. Font-Namen sind beispielsweise Times New Roman, Helvetica oder Courier.
• Schriften können Serifen besitzen oder auch serifenlos sein.
• Ein weiteres Kennzeichen einer Schrift ist die Zeichenbreite. Diese kann variabel oder konstant sein. Bei konstanter Zeichenbreite bezeichnet man eine Schrift als monospaced.
• Beispiel: Der Font, in dem diese Folien geschrieben wurden, ist die serifenlose Variante der „Latin Computer Modern“.
• Es können auch die Font-Namen Serif, SansSerif und Monospaced verwendet
Schriftarten
• Der Parameter size gibt die Schriftgröße an. Übliche Schriftgrößen für Text liegen zwischen 10 pt und 12 pt.
• Die Schriftart wird durch den Parameter style beschrieben:
Name Wert Bedeutung Font.PLAIN 0 Standard-Font
Font.BOLD 1 Fettdruck
Font.ITALIC 2 Kursivdruck
3 fetter Kursivdruck
Schriftarten
Beispiel: Die folgenden Anweisungen bewirken, dass der String "Zeichenkette" in einer Schrift mit konstanter Zeichenbreite in fettem Kursivdruck in 12-Punkt-Schrift an die Position (50,350) geschrieben wird:
Font f = new Font("Monospaced",3,12);
g.setFont(f);
g.drawString("Zeichenkette",50,350);
Schriftarten
Das folgende Beispiel gibt die drei Standardschriften in 36 Punkt aus:
public void paint(Graphics g) { Font font;
String[] arfonts = {"Serif","SansSerif","Monospaced"};
for (int i = 0; i < arfonts.length; ++i) { font = new Font(arfonts[i],Font.PLAIN,36);
g.setFont(font);
g.drawString(arfonts[i],10,30 + (i + 1) * (36 + 5));
} }
Schriftarten
• Die Klasse Font besitzt Methoden, um Informationen über den aktuellen Font zu gewinnen:
◦ String getFamily()
◦ int getStyle()
◦ int getSize()
• Die Klasse FontMetrics stellt Methoden zur Verfügung, mit denen die
Größenmaßzahlen einzelner Zeichen – wie Oberlänge, Unterlänge oder Breite –, Größen wie der Zeilenabstand oder die Länge eines Strings ermittelt werden können.
◦ int charWidth(char ch)
◦ int stringWidth(String str)
Farbmodell
Eine Möglichkeit, in Java Farben zu
benutzen, basiert auf dem RGB-Farbmodell (Rot-Grün-Blau-Farbmodell). Jede dieser drei Grundfarben wird durch 8 Bits
dargestellt. Der Anteil einer Grundfarbe kann also durch eine Dezimalzahl zwischen 0 und 255 beschrieben werden. Für die gesamte Farbtiefe ergeben sich somit 24 Bits.
Farbe Rot Grün Blau
Weiß 255 255 255
Grau 127 127 127
Schwarz 0 0 0
Rot 255 0 0
Grün 0 255 0
Blau 0 0 255
Gelb 255 255 0
Magenta 255 0 255
Cyan 0 255 255
Java unterstützt weitere Farbmodelle, in denen Farben z. B. durch Farbton, Intensität und Helligkeit dargestellt werden.
Erzeugung von Farben
• Farben werden durch die Klasse Color dargestellt. Jedes Objekt repräsentiert eine Farbe, die durch ihren RGB-Wert eindeutig gekennzeichnet ist.
• Konstruktoren:
◦ Color(int r, int g, int b)
◦ Color(float r, float g, float b)
Der erste Konstruktor erwartet ganzzahlige Werte im Bereich von 0 bis 255, der zweite Fließkommazahlen zwischen 0.0 und 1.0. Der Wert 0.0 entspricht der ganzzahligen 0, der Wert 1.0 der ganzzahligen 255.
Erzeugung von Farben
• Die Klasse Color stellt etliche Farben als statische Objekte zur Verfügung:
◦ static Color black
◦ static Color red
◦ static Color green
◦ static Color blue
◦ . . .
• Von einem bestehenden Farbobjekt kann der RGB-Wert mit den Methoden
◦ int getRed(),
◦ int getGreen() und
◦ int getBlue() ermittelt werden.
Verwendung von Farben
• Um Farben bei der Ausgabe von Schrift oder Grafik zu verwenden, muss ein Objekt der Klasse Color erzeugt und mithilfe der Methode
void setColor(Color c)
dem grafischen Kontext zugewiesen werden.
• Die Ausgabe erfolgt solange in der neuen Farbe, bis dem Kontext eine neue Farbe zugeordnet wird.
• Mit Color getColor() wird die aktuelle Farbe abgefragt.
Verwendung von Farben
Beispiel:
public void paint(Graphics g) { g.setColor(Color.red);
g.drawString("Zeichenkette",200,500);
g.setColor(new Color(200,200,0));
g.drawOval(50,400,60,160);
...
}
Die Klasse SystemColor
• Die Klasse SystemColor stellt eine Reihe von Farben zur Verfügung, die den
Farben des Desktops entsprechen. Damit können Anwendungen entwickelt werden, die im Aussehen an die Betriebssystemumgebung angepasst sind.
• Beispiele:
◦ SystemColor.desktop
Hintergrundfarbe des Desktops
◦ SystemColor.window
Hintergrundfarbe für Fenster
◦ SystemColor.text
Hintergrundfarbe für Text
Grafikprogrammierung in Java:
Fensterklassen
11.1 Grundlagen
11.2 Grafische Grundelemente 11.3 Fensterklassen
11.4 Ereignisse und Widgets 11.5 Applets
11.6 Die Swing-Klassen
Fensterklassen
Das AWT enthält eine Reihe von Fensterklassen, die über eine Vererbungslinie miteinander verbunden sind. An der Spitze steht die Klasse Component:
• Component
◦ Container
∗ Panel - Applet
∗ Window - Frame - Dialog
· FileDialog
◦ Button
◦ Canvas
◦ Checkbox
◦ Choice
◦ Label
◦ List
◦ Scrollbar
◦ Textcomponent
Fensterklassen
• Component ist eine abstrakte Klasse, deren Objekte Programmelemente darstellen, die eine Größe und eine Position besitzen und die Ereignisse senden und auf
Ereignisse reagieren können.
• Container ist eine konkrete Klasse. Sie erlaubt es, innerhalb einer Komponente weitere Komponenten aufzunehmen. Container stellt Methoden, um
Komponenten hinzuzufügen oder zu entfernen, bereit. Mit den LayoutManager-Klassen werden die Komponenten positioniert.
• LayoutManager, LayoutManager2 sind Interfaces. Implementierende Klassen sind beispielsweise BorderLayout, FlowLayout, GridLayout, . . .
Fensterklassen
• Panel ist die einfachste konkrete Klasse mit den Eigenschaften von Component und Container.
• Applet ist eine direkte Unterklasse von Panel. Ein Applet besitzt also die Fähigkeiten der Klassen Component und Container. Diese Klasse spielt eine entscheidende Rolle in der Entwicklung von Applets.
• Die Klasse Window abstrahiert ein Top-Level-Window ohne Rahmen, Titelleiste und Menü. Sie ist für Anwendungen geeignet, die die Kontrolle über das gesamte Fenster benötigen.
• Frame repräsentiert ein Top-Level-Window mit Rahmen, Titelleiste und
optionalem Menü. Einem Frame kann ein Icon zugeordnet werden, das angezeigt
Aufrufen und Schließen eines Fensters
• Um ein Fenster auf dem Bildschirm anzuzeigen, muss zunächst eine geeignete Fensterklasse instanziiert werden. Dafür kommen Klassen wie Window, Frame, Dialog, Applet und FileDialog in Frage. Die Klassen haben unterschiedliche Konstruktoren.
• Nach der Instanziierung wird die Methode
setVisible(boolean visible)
aufgerufen, um das Fenster anzuzeigen. Wird true übergeben, wird das Fenster angezeigt, andernfalls geschlossen.
• Um ein Fenster zu schließen, sind die Methoden setVisible(false) und aufzurufen.
Eigenschaften eines Fensters
• Größe und Position, geerbt von Component
• Aktivierungskomponente, geerbt von Component
• Fensterelemente
◦ Titelleiste, Menü, Icon, Mauscursor, Standardfont, Vorder- und Hintergrundfarbe
• Die Eigenschaften eines Fensters können mithilfe spezieller Methoden gesetzt und abgefragt werden.
• Beispiel: Objekte der Klasse Frame besitzen einen Rahmen, eine Titelleiste und optional ein Menü, Objekte der Klasse Window hingegen nicht.
Grafikprogrammierung in Java:
Ereignisse und Widgets
11.1 Grundlagen
11.2 Grafische Grundelemente 11.3 Fensterklassen
11.4 Ereignisse und Widgets 11.5 Applets
11.6 Die Swing-Klassen
Ereignisgesteuerte Programmierung
• Ereignisse sind beispielsweise das Drücken einer Taste, die Betätigung des Rollbalkens oder die Bewegung der Maus.
• Jedes Ereignis besitzt eine Quelle (Source).
• Ein Ereignis kann von Beobachtern (Listener) wahrgenommen werden. Die
Anmeldung von Beobachtern zur Benachrichtigung vom Eintreten eines Ereignisses ist frei programmierbar und muss immer explizit erfolgen.
• Es ist nicht festgelegt, in welcher Reihenfolge die Beobachter vom Eintreten eines Ereignisses informiert werden. Sichergestellt ist lediglich, dass jeder Beobachter eine Kopie des ursprünglichen Ereignisses erhält.
Ereignisgesteuerte Programmierung
• Bei der Verbreitung von Ereignissen ist zwischen den Modi single-cast und
multi-cast zu unterscheiden. Für Single-Cast-Ereignisse wird der Beobachter mit einer setxxListener-Methode gesetzt, für Multi-Cast-Ereignisse wird ein
Beobachter mit einer addxxListener-Methode der Menge der Beobachter hinzugefügt.
• Eine Adapter-Klasse ist eine Klasse, die eine gegebene Schnittstelle implementiert, indem sie jede abstrakte Methode durch einen leeren Rumpf realisiert.
Adapter-Klassen werden verwendet, wenn von einer Schnittstelle lediglich ein Teil der Methoden benötigt wird, der Rest aber uninteressant ist. In diesem Fall leitet man eine neue Klasse aus der Adapter-Klasse ab und überlagert nur die
erforderlichen Methoden.
Ereignisklassen
• EventObject
◦ AWTEvent
∗ ComponentEvent - FocusEvent - InputEvent - KeyEvent - MouseEvent - ContainerEvent - WindowEvent
∗ ActionEvent
∗ AdjustmentEvent
∗ ItemEvent
∗ TextEvent
EventListener-Schnittstellen
• EventListener
◦ FocusListener
◦ ActionListener
◦ AdjustmentListener
◦ ItemListener
◦ TextListener
◦ KeyListener
◦ MouseListener
◦ MouseMotionListener
◦ WindowListener
◦ ContainerListener
◦ ComponentListener
Low-Level-Events
Beispiel: Window-Events
• windowOpened
• windowActivated, windowDeactivated
• windowClosed
• windowClosing
• windowIconified, windowDeiconified
Widgets
Fensterelemente mit Ein- und/oder Ausgabefunktionalität werden als Widgets (window gadgets) bezeichnet. Die Anordnung der Widgets in einem Fenster wird durch den Layout-Manager durchgeführt. Widgets sind beispielsweise:
• Label
• Rollbalken
• Schaltflächen (buttons)
• Checkboxen und Checkboxgruppen (radio buttons)
Widgets
• Textfelder und Textbereiche
• Auswahlboxen
• Listen
• Canvas
• Panels
• Dateidialogboxen (nicht für Applets)
• Menüs (nicht für Applets)
Schritte zur Realisierung eines Widgets
• Schnittstelle angeben
• Widget deklarieren und initialisieren
• Widget dem Layout hinzufügen
• Beobachter registrieren
• Ereignis behandeln
Man beachte, dass mehrere Widgettypen dieselbe Ereignisklasse verwenden, z. B.
Beispiel: Rollbalken
Als erstes Beispiel betrachten wir jetzt die Programmierung eines Rollbalkens.
import java.awt.*;
import java.awt.event.*;
public class WindowBlind extends Frame implements AdjustmentListener {
private Scrollbar schieber;
private int schieberWert;
public WindowBlind() {
setLayout(new FlowLayout());
setBackground(Color.white);
schieber = new Scrollbar(Scrollbar.HORIZONTAL,0,1,0,101);
add(schieber);
addWindowListener(new WindowClosingAdapter());
schieber.addAdjustmentListener(this);
}
public void paint(Graphics g) {
g.drawString("Rollbalkenwert ist " + schieberWert,120,200);
g.setColor(Color.red);
g.drawRect(40,80,60,100);
g.fillRect(40,80,60,schieberWert);
g.setColor(Color.blue);
g.drawRect(120,80,60,100);
g.fillRect(120,80 + schieberWert,60,100 - schieberWert);
g.setColor(Color.green);
g.drawRect(200,80,60,100);
g.fillRect(200,80,60,100 - schieberWert);
}
public void adjustmentValueChanged(AdjustmentEvent e) { schieberWert = schieber.getValue();
repaint();
}
public static void main(String[] args) { WindowBlind f = new WindowBlind();
f.setSize(400,300);
f.setVisible(true);
} }
Beispiel: Label und Button
... implements ActionListener { private Label title;
private Button knopf1, knopf2;
private int anzahl = 0;
public Konstruktor() {
setLayout(new FlowLayout());
title = new Label("Zählknopf:");
knopf1 = new Button("Drück mich!");
knopf2 = new Button("Ende");
add(title); add(knopf1); add(knopf2);
knopf1.addActionListener(this);
knopf2.addActionListener(this);
}
public void paint(Graphics g) {
g.drawString("Der Knopf wurde " + anzahl +
" mal gedrückt.",10,80);
}
public void actionPerformed(ActionEvent event) { anzahl++;
if (event.getSource() == knopf2) System.exit(0);
repaint();
} }
AbstractButton
• Die abstrakte Klasse AbstractButton ist eine Unterklasse der Klasse JComponent (s. Abschnitt Swing-Klassen).
• Die abstrakte Klasse AbstractButton enthält die Methode void doClick() durch die in Implementierungen dieser Klasse ein Klick programmatisch ausgeführt werden kann.
• Beispiele für Unterklassen von AbstractButton sind die Klassen JButton, JToggleButton und JMenuItem.
Weitere Widgets
• Textfield:
ActionListener, addActionListener
void actionPerformed(ActionEvent event)
• Checkbox, Checkboxgroup:
ItemListener, addItemListener
void itemStateChanged(ItemEvent event)
• Choice:
ItemListener, addItem, addItemListener void itemStateChanged(ItemEvent event)
Grafikprogrammierung in Java:
Applets
11.1 Grundlagen
11.2 Grafische Grundelemente 11.3 Fensterklassen
11.4 Ereignisse und Widgets 11.5 Applets
11.6 Die Swing-Klassen
Anwendungen und Applets
• Anwendungen (Applikationen)
◦ Anwendungen bilden eigenständige Programme. Zur Ausführung benötigen sie nur den Java-Interpreter und die .class-Dateien der beteiligten Klassen.
◦ Jede Klasse, die die Methode public static void main enthält, kann als Anwendung benutzt werden.
• Applets (little applications)
◦ Applets sind kleine Programme, die in eine Html-Seite eingebettet sind und nur innerhalb eines Web-Browsers oder eines Applet-Viewers ausgeführt werden können.
◦ Applets werden nicht durch die Methode main gestartet, sondern müssen aus der Klasse Applet abgeleitet und entsprechend konstruiert werden.
Ein kleines Applet: Java-Datei
import java.awt.*;
import java.applet.*;
public class MinimalApplet extends Applet { public void paint(Graphics g) {
g.drawString("Test-Ausgabe",0,20);
} }
Ein kleines Applet: Html-Seite
<html>
<head>
<title>Applet-Test</title>
</head>
<body>
<applet code="MinimalApplet" width=600 height=800>
Hier steht das Applet.</applet>
</body>
</html>
Anwendungen und Applets
• Ein Applet wird immer aus der Klasse Applet abgeleitet. Bei einer Anwendung ist es dagegen gleichgültig, woraus die Hauptklasse abgeleitet wird.
• Eine Anwendung wird gestartet, indem vom Java-Interpreter die Methode main aufgerufen wird. Das Starten eines Applets wird dadurch erreicht, dass der Browser oder der Applet-Viewer die Applet-Klasse instanziiert und die Methoden init und start aufruft.
• Aus Gründen der Sicherheit darf ein Applet in der Regel weder auf Dateien des lokalen Rechners zugreifen noch externe Programme auf dem Rechner starten.
Anwendungen und Applets
• Ein Applet arbeitet immer ereignisorientiert. Im Gegensatz dazu kann eine Anwendung auf die Behandlung von Ereignissen verzichten und alle Ein- und Ausgaben textbasiert durchführen.
• Im Vergleich zu Anwendungen bieten Applets einige zusätzliche Möglichkeiten.
Die Klasse Applet
Die Klasse Applet steht in der Vererbungshierarchie unter der Klasse Component und Container. Sie besitzt damit deren Eigenschaften.
• Component
◦ Container
∗ Panel - Applet
Bezüglich der Reaktion auf Ereignisse und die Registrierung und Programmierung von Listener-Klassen verhält sich ein Applet wie jedes andere Fenster.
Methoden
• init(): Initialisierung eines Applets
• start(): Start eines Applets
• stop(): Stopp eines Applets,
z. B. beim Laden einer anderen Seite.
start und stop können mehrfach während der Lebensdauer eines Applets aufgerufen werden.
• paint(Graphics g): Methode zum Zeichnen
• destroy(): Beenden eines Applets
Beispiel: Rollbalken
Als Beispiel schreiben wir das Rollbalkenprogramm als Applet.
import java.awt.*;
import java.awt.event.*;
import java.applet.Applet;
public class WindowBlind extends Applet implements AdjustmentListener {
private Scrollbar schieber;
private int schieberWert;
public void init () {
setBackground(Color.white);
schieber = new Scrollbar(Scrollbar.HORIZONTAL,0,1,0,101);
add(schieber);
schieber.addAdjustmentListener(this);
}
public void paint(Graphics g) {
showStatus("Rollbalkenwert ist " + schieberWert);
g.setColor(Color.red);
g.drawRect(40,80,60,100);
g.fillRect(40,80,60,schieberWert);
g.setColor(Color.blue);
g.drawRect(120,80,60,100);
g.fillRect(120,80 + schieberWert,60,100 - schieberWert);
g.setColor(Color.green);
g.drawRect(200,80,60,100);
g.fillRect(200,80,60,100 - schieberWert);
}
public void adjustmentValueChanged(AdjustmentEvent e) { schieberWert = schieber.getValue();
repaint();
} }
Anwendungen und Applets
Dies sind die wesentlichen Schritte, um eine Anwendung in ein Applet zu konvertieren.
Die Anwendung darf nur Elemente benutzen, die auch für Applets erlaubt sind.
• Html-Seite erzeugen
• main-Methode löschen
• Aus dem Paket java.applet importieren, JApplet statt JFrame erweitern
• Konstruktor in init umbenennen, ggf. start, stop, destroy schreiben
• Layout festlegen
• Bei mehreren Klassen: jar-Datei erzeugen
Anwendungen und Applets
Dies sind die wesentlichen Schritte, um ein Applet in eine Anwendung zu konvertieren.
Das Applet darf keine speziellen Methoden der applet-Klasse verwenden.
• import applet löschen
• frame statt applet erweitern
• init als Konstruktor schreiben
• main-Methode erzeugen
• Methode zum Fenster schließen hinzufügen
• Layout festlegen
Grafikprogrammierung in Java:
Die Swing-Klassen
11.1 Grundlagen
11.2 Grafische Grundelemente 11.3 Fensterklassen
11.4 Ereignisse und Widgets 11.5 Applets
11.6 Die Swing-Klassen
Die Java Foundation Classes
Seit der Version 1.2 des JDK werden die grafischen Fähigkeiten von Java unter dem Begriff Java Foundation Classes (JFC) zusammengefasst. Die drei wichtigsten
Bestandteile sind:
• Das Abstract Window Toolkit (AWT) stellt elementare Grafik- und
Fensterfunktionen auf der Basis der jeweiligen Zielmaschine zur Verfügung.
• Das Swing Toolset bietet darüber hinausgehende Möglichkeiten zur Konstruktion komplexer grafischer Oberflächen. Insbesondere wird ein „pluggable look and feel“
ermöglicht.
• Die dritte wichtige Komponente ist die Java 2D API (Klassen für zweidimensionale Grafikverarbeitung) mit diversen Grafikoperationen und Bildbearbeitungsroutinen.
Die Java Foundation Classes
Die Klassen lassen sich in vier Gruppen einteilen:
• Behälter (container) bestehen aus Komponenten, die auch selbst Komponenten enthalten können. Beispielsweise sind die Objekte der Klassen JFrame und
JWindow Behälter.
• Komponenten enthalten die Bestandteile der Fenster. Komponenten sind beispielsweise Beschriftungen (label), Auswahlfelder, Knöpfe (buttons), . . .
• Layout-Manager, Fonts und Farben bestimmen die Anordnung und das Aussehen der Komponenten in einem Behälter.
• Mit den Ereignisklassen werden mögliche Ereignisse, Beobachter und Reaktionen
Die Java Foundation Classes
• Die Swing-Bibliothek ersetzt und erweitert die Komponenten- und Behälterklassen des AWTs.
• Die AWT-Klassen zu Schrift, Farbe und Layout-Manager sowie die Ereignisklassen werden weiterverwendet.
• Die AWT-Klassen befinden sich im Paket java.awt, die Swingklassen in javax.swing.
• Die Klassen der Swing-Bibliothek beginnen in der Regel mit dem Buchstaben J.
AWT und Swing im Vergleich
• Im AWT wird der Peer-Ansatz verfolgt: Alle AWT-Komponenten reichen die
auszuführenden Aktionen an plattformspezifische GUI-Objekte, sogenannte Peers, weiter. Komponenten, die solche Peer-Objekte benötigen, werden als
schwergewichtig bezeichnet. Diese Komponenten sehen auf unterschiedlichen Betriebssystemen unterschiedlich aus. Es können nur die Funktionalitäten
bereitgestellt werden, die auf dem jeweiligen Betriebssystem zur Verfügung stehen.
• Fast alle Swing-Komponenten sind vollständig in Java geschrieben und werden deshalb leichtgewichtig genannt. Form und Funktion sind daher weitgehend unabhängig vom Betriebssystem. Die Oberfläche kann plattformunabhängig
gestaltet werden und ist noch zur Laufzeit veränderbar (pluggable look and feel).
Eigenschaften von Swing
• 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.
• Ein Swing-Button unter Windows wird nicht mehr vom Windows-UI-Manager dargestellt, sondern von Swing selbst gezeichnet.
• Diese Vorgehensweise bietet Vorteile. Zwei Beispiele:
◦ Plattformspezifische Besonderheiten fallen weg.
◦ Es entfallen auch Unterschiede in der Bedienung.
Eigenschaften von Swing
Guido Krüger, Heiko Hansen: Handbuch der Java-Programmierung.
• Eine bemerkenswerte Eigenschaft von Swing ist die Möglichkeit, das Look-and-Feel (Aussehen und Bedienung einer Anwendung) zur Laufzeit umzuschalten.
• Dieses als Pluggable Look-and-Feel bezeichnete Feature ermöglicht es
beispielsweise einem Windows-Anwender, zwischen unterschiedlichen vordefinierten Look-and-Feels (zum Beispiel Metal, Motif und Windows) zu wählen.
• Benutzer anderer Betriebssysteme können andere Auswahlmöglichkeiten haben oder eigene Look-and-Feels zu schreiben.
• Seit Java 7 gibt es ein viertes Standard-Look-and-Feel, das Nimbus-Look-and-Feel.
Wiederholung: Ein einfaches AWT-Beispiel
import java.awt.*;
public class FrameOhneInhaltAWT {
public static void main(String[] args) { Frame fenster = new Frame();
fenster.setTitle("Ein AWT-Fenster");
fenster.setLocation(500,400);
fenster.setSize(300,150);
fenster.setVisible(true);
}
Ein einfaches Swing-Beispiel
import javax.swing.*;
public class FrameOhneInhaltSwing {
public static void main(String[] args) { JFrame fenster = new JFrame();
fenster.setTitle("Ein Swing-Fenster");
fenster.setLocation(500,400);
fenster.setSize(300,150);
fenster.setVisible(true);
fenster.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
} }
AWT und Swing im Vergleich
• Es wird aus unterschiedlichen Paketen importiert:
import java.awt.* bzw. import javax.swing.*.
• Die Behälterklassen sind verschieden: Frame bzw. JFrame.
• In der Swing-Variante gibt es eine einfache Möglichkeit zum Schließen eines Fensters: setDefaultCloseOperation.
• Beim Lauf erzeugt die Swingklasse einen grauen Hintergrund.
Eine abgeleitete Swing-Klasse
import javax.swing.*;
public class FrameOhneInhalt extends JFrame { public FrameOhneInhalt () { }
public static void main(String[] args) {
FrameOhneInhalt fenster = new FrameOhneInhalt();
fenster.setTitle("Frame ohne Inhalt");
fenster.setLocation(500,500);
fenster.setSize(300,150);
fenster.setVisible(true);
fenster.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
Ein Fenster mit Text
public class FrameMitText extends JFrame {
Container c; // Container dieses Frames
JLabel beschriftung; // Label, das im Frame erscheinen soll public FrameMitText() {
c = getContentPane();
c.setLayout(new FlowLayout());
beschriftung = new JLabel("Label-Text im Frame");
c.add(beschriftung);
}
public static void main(String[] args) {
FrameMitText fenster = new FrameMitText();
fenster.setTitle("Frame mit Text im Label"); fenster.setLocation(200,200);
fenster.setSize(300,150); fenster.setVisible(true);
fenster.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Einordnung der Swingklassen
• Component
◦ Container
∗ Panel - Applet
· JApplet
∗ Window - JWindow - Frame
· JFrame - Dialog
· JDialog
∗ JComponent
◦ Button, Label, weitere AWT-Komponenten
Einordnung der Swingklassen
• JComponent
◦ JLabel
◦ AbstractButton
◦ JComboBox
◦ JMenuBar
◦ JList
◦ JScrollbar
◦ JProgressbar
◦ JTextComponent
◦ JPanel
◦ JTable
◦ ...
Einordnung der Swingklassen
• Die Swing-Behälter-Klassen JFrame, JWindow, . . . sind Erweiterungen der entsprechenden AWT-Klassen.
• Die Swing-Komponenten-Klassen bilden eine eigene Hierarchie unterhalb von Container.
• Alle Swing-Klassen stehen unterhalb von Container und erben somit von Component und Container.
Die gleichzeitige Verwendung von
AWT- und Swing-Komponenten ist zu vermeiden.
Wiederholung: Die Klasse Component
Die abstrakte Klasse Component steht an oberster Stelle der JFC-Hierachie. Sie stellt Basismethoden zur Verfügung, die alle AWT- und Swingkomponenten gemeinsam
nutzen können. Die wichtigsten sind:
• Color getBackground(), Color getForeground()
• void setBackground(Color c), void setForeground(Color c)
• Font getFont, void setFont(Font c)
• int getHeight(), int getWidth()
• void setSize(int width, int height)
• setLocation(int x, int y)
• boolean isEnabled(), void setEnabled(boolean b)
• boolean isVisible(), void setVisible(boolean b)
Wiederholung: Die Klasse Container
Behälter sind spezielle Komponenten, die andere Komponenten enthalten können. Die Klasse Container stellt demzufolge Methoden zum Einfügen, Verwalten und
Entfernen von Komponenten zu Verfügung. Die Komponenten werden in einer Liste geführt, wobei die Reihenfolge sich durch die Reihenfolge der Einfügungen ergibt oder durch einen Listenindex bestimmt werden kann. Die Liste wird zur Anordnung der Komponenten in dem Behälterobjekt benötigt.
• Component add(Component comp)
• Component add(Component comp, int index)
• Component[] getComponents()
• void remove(Component comp)
• void setLayout(LayoutManager mgr)
Die Klasse JComponent
Die abstrakte Klasse JComponent dient als Basisklasse für die Swingkomponenten mit Ausnahme der Klassen Component und Container. Von diesen beiden Klassen erbt JComponent und überschreibt dabei einige Methoden. Komponenten können sowohl durchsichtig (opaque: false) als auch undurchsichtig (opaque: true) sein und mit einem erläuternden Text, dem sog. Tooltip, versehen werden. Der Text erscheint, wenn der Mauszeiger einige Sekunden auf der Komponente ruht.
• boolean isOpaque()
• void setOpaque(boolean b)
• String getToolTipText()
• void setToolTipText(String text)
Die Klasse JComponent
All Implemented Interfaces:
ImageObserver, MenuContainer, Serializable Direct Known Subclasses:
AbstractButton, BasicInternalFrameTitlePane, Box, Box.Filler, JColorChooser, JComboBox, JFileChooser, JInternalFrame,
JInternalFrame.JDesktopIcon, JLabel, JLayeredPane, JList, JMenuBar, JOptionPane, JPanel, JPopupMenu, JProgressBar, JRootPane, JScrollBar, JScrollPane, JSeparator, JSlider, JSpinner, JSplitPane, JTabbedPane, JTable, JTableHeader, JTextComponent, JToolBar, JToolTip, JTree, JViewport
Komponenten: Inhalt und Anordnung
Ein Behälterobjekt enthält in der Regel eine oder mehrere Komponenten. Die Komponenten können Texte, Bilder, Zeichnungen, . . . enthalten. Mithilfe eines Layoutmanagers werden die Komponenten innerhalb des Behälters angeordnet.
• Mit der Klasse Font (java.awt) können Schriften ausgewählt werden.
• Die Klasse Color (java.awt) stellt Farben zur Verfügung.
• Die abstrakte Klasse Graphics (java.awt) bietet Möglichkeiten zur Erstellung von Zeichnungen.
• Die Schnittstellen LayoutManager und LayoutManager2 (java.awt) offerieren Methoden zur Anordnung der Komponenten. Die Schnittstelle Border und die Klasse BorderFactory (javax.swing) bieten Möglichkeiten zur Gestaltung der Grenzen zwischen Komponenten.
Die Klasse FlowLayout
Bei Verwendung der Klasse FlowLayout werden die Komponenten fließend, d. h.
zeilenweise von links nach rechts, angeordnet. Innerhalb einer Zeile werden die
Komponenten zentriert. Zwischen den Zeilen befindet sich ein Standardabstand von 5 Pixeln, der aber geändert werden kann. Mit dem Parameter align kann bestimmt werden, ob die Komponenten links- oder rechtsbündig bzw. zentriert dargestellt
werden. hp und vp bestimmen die Abstände zwischen den Komponenten und Zeilen.
• FlowLayout()
• FlowLayout(int align)
• FlowLayout(int align, int hp, int vp)
Die Klasse BorderLayout
Bei diesem Layout wird die Behälterfläche in die fünf Bereiche Nord, Ost, Süd, West und Zentrum aufgeteilt. In jedes dieser Gebiete kann eine Komponente eingefügt werden. Die Größe von Nord, Ost, Süd und West ergibt sich aus dem jeweiligen
Objekt, während die Größe des Zentrums an die Gesamtgröße des Behälters angepasst wird. Beispielsweise wird durch add(...,BorderLayout.NORTH) ein Objekt im
oberen und durch add(...,BorderLayout.CENTER) im mittleren Bereich hinzugefügt.
• BorderLayout()
• BorderLayout(int hp, int vp)
Die Klasse GridLayout
Die Behälterfläche wird gitterartig in z Zeilen und s Spalten aufgeteilt. Die Werte z und s werden bereits dem Konstruktor übergeben.
• GridLayout()
• GridLayout(int z, int s)
• GridLayout(int z, int s, int hp, int vp)
Es gibt etliche weitere Layout-Klassen, z. B. GridBagLayout, BoxLayout,
SpringLayout, OverlayLayout. Im Package java.awt befinden sich die zwei Schnittstellen LayoutManager und LayoutManager2. Sie enthalten Hinweise auf Klassen, die diese Schnittstellen implementieren.
Die Klasse Graphics
• Die abstrakte Klasse Graphics stellt zahlreiche Methoden bereit, die es
ermöglichen, innerhalb des Koordinatensystems einer Komponente zu zeichnen.
Hierzu zählen die Methoden, die wir bereits kennengelernt haben: drawLine,
drawRect, . . . . In einem grafischen Kontext sind die gegenwärtigen Einstellungen zu Schrift und Farbe sowie die zu bearbeitende Komponente gespeichert.
• Die Klasse Graphics2D ist aus Graphics abgeleitet und erweitert diese um viele Aspekte, insbesondere um solche zur Darstellung von zweidimensionalen
Zeichnungen.
• Für die Darstellung einer einzelnen Swing-Komponente ist der Repaint-Manager zuständig. Er sorgt dafür, dass beim erstmaligen Erscheinen und bei Veränderungen die Methode public void paint(Graphics g) aufgerufen wird.
Die Komponentenklasse JLabel
Die Klasse JLabel dient zur Darstellung von Texten und Bildern.
public class MyFrame extends JFrame {
Container c; // Container dieses Frames
JLabel lab; // Label, das im Frame erscheinen soll public MyFrame() {
c = getContentPane();
c.setLayout(new FlowLayout());
Icon bild = new ImageIcon("xxx.jpg");
lab = new JLabel("Text", bild, JLabel.CENTER);
lab.setHorizontalTextPosition(JLabel.CENTER);
lab.setVerticalTextPosition(JLabel.BOTTOM);
c.add(lab);
} ...
Die Komponentenklasse AbstractButton
Die abstrakte Klasse bietet verschiedene Arten von Schaltflächen und Knöpfen. Die wichtigsten Implementierungen sind:
• JButton (einfache Schaltfläche zum Auslösen von Aktionen)
• JToggleButton (Schalter mit zwei Zuständen)
◦ JCheckBox (Kennzeichnung durch Häkchen)
◦ JRadioButton (sich ausschließende Schalter)
• JMenuItem (Schaltflächen in einem Menü)
◦ JMenu
◦ JCheckBoxMenuItem
◦ JRadioButtonMenuItem
Beispiel: JRadioButton
Container c;
JRadioButton rb[] = new JRadioButton[4];
...
public Konstruktor() { c = getContentPane();
c.setLayout(new FlowLayout());
ButtonGroup bg = new ButtonGroup();
for (int i = 0; i < 4; i++) {
rb[i] = new JRadioButton("Box " + (i+1));
bg.add(rb[i]);
c.add(rb[i]);
} }
Die Komponentenklasse JComboBox
• Ein Objekt der Klasse JComboBox ist eine aufklappbare Auswahlliste, die man mithilfe der Maus oder der Tastatur aufklappen und in der man einen Eintrag auswählen kann.
• Angezeigt wird dabei jeweils der ausgewählte Eintrag und ein Pfeil nach unten, der anzeigt, dass es sich um eine aufklappbare Liste handelt.
Beispiel: JComboBox
Container c;
JComboBox vornamen, nachnamen;
public Konstruktor() { c = getContentPane();
c.setLayout(new FlowLayout());
String[] namen = {"Hans", "Klaus", "Sabine", "Erika"};
vornamen = new JComboBox(namen);
nachnamen = new JComboBox();
nachnamen.addItem("Meyer"); nachnamen.addItem("Müller");
nachnamen.addItem("Schulze"); nachnamen.addItem("Lehmann");
nachnamen.setSelectedIndex(2);
c.add(vornamen);
c.add(nachnamen);
}
Die Komponentenklasse JList
• Im Unterschied zur JComboBox-Objekt stellt ein Objekt der Klasse JList eine Auswahlliste dar, die bereits aufgeklappt ist und daher komplett angezeigt wird.
• In der API steht in der Klasse JList:
A component that displays a list of objects and allows the user to select one or more items.
• Durch Drücken der Taste Ctrl/Strg können mehrere Einträge ausgewählt
werden. Die ausgewählten Einträge werden markiert. Mit der Shift-Taste kann ein ganzer Bereich markiert werden.
Die Komponentenklasse JTextComponent
Die abstrakte Klasse bietet verschiedene Möglichkeiten zur Eingabe von Text. Die wichtigsten Implementierungen sind:
• JTextArea (Eingabe mehrzeiliger Texte)
• JTextField (Eingabe einzeiliger Texte)
◦ JPasswordField (Eingabe einzeiliger geschützter Texte)
• JTextPane (Eingabe von formatierten Texten)
◦ JHTMLPane (z. B. HTML-Texte)
Die Komponentenklasse JScrollPane
• Objekte der Klasse JScrollPane sind in der Lage, andere Komponenten
aufzunehmen und in einen Darstellungsbereich einzubetten, der mit horizontalen und vertikalen Bildlaufleisten ausgestattet ist.
• Hierdurch wird eine ausschnittsweise Sicht auf die Komponenten ermöglicht.
• Der jeweilige Ausschnitt wird mit Schiebereglern (scrollbars), die sich am Bildrand befinden, festgelegt.
Die Komponentenklasse JPanel
• Objekte der Klasse JPanel können andere Komponenten enthalten. Sie sind daher eigentlich keine Komponenten, sondern Behälter.
• JPanel ist die Basisklasse für Container, die nicht Hauptfenster sind.
Standardmäßig verwendet JPanel das FlowLayout.
• Objekte der Klasse JPanel werden zum Strukturieren von Behältern verwendet – und sind aus dieser Sicht Komponenten anderer Behälter.
Die Behälterklasse JFrame
• Die Klasse JFrame ist die wichtigste Top-Level-Behälterklasse.
• Sie erbt von Frame, ihre Objekte sind daher Fenster mit Rahmen.
• In der Titelleiste des Rahmens befinden sich die üblichen System-Menü-Einträge.
• Zusätzlich zu den Methoden von Frame stellt JFrame weitere zur Verfügung, z. B. zum Schließen von Fenstern.
Die Behälterklasse JWindow
• Wie JFrame ist auch JWindow eine Top-Level-Behälterklasse.
• Sie erbt von Window, die Objekte sind daher rahmenlose Fenster.
• Ein JWindow-Objekt kann einem JFrame-Objekt oder einem anderem
JWindow-Objekt gehören. In diesem Fall wird das JWindow-Objekt mit seinem Besitzer gemeinsam minimiert und maximiert.
• Die Konstruktoren JWindow(Frame owner) und JWindow(Window owner) erzeugen rahmenlose Fenster, die dem owner gehören. Sie werden zusammen mit dem owner minimiert und maximiert.
Die Behälterklasse JDialog
• Die Klasse JDialog wird dazu benutzt, um Dialogfenster darzustellen.
• Dies sind Fenster, die nur solange erscheinen, bis ein Dialog mit dem Benutzer/der Benutzerin abgewickelt wurde.
• Ein JDialog-Fenster kann einem übergeordneten Fenster gehören. Dieses
übergeordnete kann solange für Benutzereingaben gesperrt werden, bis der Dialog im Dialogfenster beendet ist.
Die Klassen JMenuBar und JToolBar
• Einem JFrame-Objekt kann eine Menüleiste hinzugefügt werden. Dies erfolgt mit Objekten der Klasse JMenuBar.
• Eine Menüleiste verwaltet eine Liste von Menüs vom Typ JMenu.
• Neben Menüleisten sieht man häufig Werkzeugleisten (toolbars). Hierbei handelt es sich um spezielle Behälter, die meistens Button-Objekte enthalten, die häufig
verwendete Funktionalitäten auslösen können.
• Eine Werkzeugleiste kann als Objekt der Klasse JToolBar erzeugt werden.
Die Klasse JApplet
• Zur Programmierung von Applets stellt die Swing-Bibliothek die Klasse JApplet zur Verfügung.
• JApplet ist direkt aus Applet abgeleitet.
• Die Klasse JApplet steht also in der Hierachie unter Component, Container und Applet und erbt daher die Methoden dieser Klassen.
Prinzipielle Vorgehensweise
• Durch Instanziieren einer (eigenen) Fensterklasse wird ein Fensterobjekt erzeugt.
Für das Objekt werden Location, Size und Title festgelegt, es wird sichtbar
gemacht, ... Die Klasse geht in der Regel aus der Ableitung einer Behälterklasse (zum Beispiel JFrame, JWindow, ...) hervor.
• Das Layout und der grafische Kontext werden festgelegt.
• Die Komponenten werden dem Fensterobjekt hinzugefügt (zum Beispiel im Konstruktor der Fensterklasse).
• Für jede Ereignisquelle werden ein oder mehrere Ereignisempfänger (Beobachter) sowie die Aktionen zur Ereignisbehandlung definiert. Die Ereignisempfänger werden bei der zuständigen Ereignisquelle registriert.
Wiederholung: Adapterklassen
• Eine Adapterklasse implementiert eine Schnittstelle durch leere Rümpfe.
• Zu jeder Low-Level-Listener-Schnittstelle mit mehr als einer Methode existiert eine Adapterklasse. Ist XxxListener der Name der Schnittstelle, so heißt die
Adapterklasse XxxAdapter. Man schreibt also
class MeinListener extends XxxAdapter statt
class MeinListener implements XxxListener.
• Beispielsweise enthält die Schnittstelle ActionListener nur eine Methode, WindowListener jedoch – wie bereits gesehen – mehrere.
Strukturierung von Behälter- und Beobachterklasse
• Die Beobachterklasse wird als innere Klasse realisiert.
• Die Beobachterklasse wird als anonyme Klasse realisiert.
• Die Fensterklasse wird selbst zur Beobachterklasse.
• Die Beobachterklasse ist eine selbstständige Klasse. Ihr muss der Behälter als Parameter übergeben werden.
Wir erläutern die Möglichkeiten an einem Beispiel zur Wechsel der Hintergrundfarbe.
Die folgenden Programme wurden D. Ratz, J. Scheffler, D. Seese, J. Wiesenberger:
Grundkurs Programmieren in Java entnommen.
Realisierung als innere Klasse
public class Farbwechsel1 extends JFrame { Container c;
JButton button;
public Farbwechsel1() { c = getContentPane();
button = new JButton("Hintergrundfarbe wechseln");
c.add(button, BorderLayout.NORTH);
ButtonListener bL = new ButtonListener();
button.addActionListener(bL);
}
class ButtonListener implements ActionListener { public void actionPerformed(ActionEvent e) {
float zufall = (float) Math.random();
Color grauton = new Color(zufall,zufall,zufall);
c.setBackground(grauton);
} }
public static void main(String[] args) {
Farbwechsel1 fenster = new Farbwechsel1();
fenster.setTitle("Farbwechsel");
fenster.setSize(200,100);
fenster.setVisible(true);
fenster.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
} }
Realisierung als anonyme Klasse
public class Farbwechsel2 extends JFrame { Container c;
JButton button;
public Farbwechsel2() { c = getContentPane();
button = new JButton("Hintergrundfarbe wechseln");
c.add(button, BorderLayout.NORTH);
ActionListener bL = new ActionListener() {
public void actionPerformed(ActionEvent e) { ... } };
button.addActionListener(bL);
}
public static void main(String[] args) { ... } }
Fensterklasse als Beobachterklasse
public class Farbwechsel3 extends JFrame implements ActionListener { Container c;
JButton button;
public Farbwechsel3() { c = getContentPane();
button = new JButton("Hintergrundfarbe wechseln");
c.add(button, BorderLayout.NORTH);
button.addActionListener(this);
}
public void actionPerformed(ActionEvent e) { ... } public static void main(String[] args) { ... }
}
Beobachterklasse als selbstständige Klasse
public class Farbwechsel4 extends JFrame { Container c;
JButton button;
public Farbwechsel4() { c = getContentPane();
button = new JButton("Hintergrundfarbe wechseln");
c.add(button, BorderLayout.NORTH);
ButtonListener bL = new ButtonListener(c);
button.addActionListener(bL);
}
public static void main(String[] args) { ... } }
Beobachterklasse als selbstständige Klasse
public class ButtonListener implements ActionListener { Container c;
public ButtonListener(Container c) { this.c = c;
}
public void actionPerformed(ActionEvent e) { float zufall = (float) Math.random();
Color grauton = new Color(zufall,zufall,zufall);
c.setBackground(grauton);
} }
Beispiel: Fenster mit Menü- und Werkzeugleiste
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Bilderrahmen extends JFrame {
Container c; // Container dieses Frames JMenuBar menuBar; // Menueleiste
JMenu menu; // Menue
JMenuItem menuItem; // Menue-Eintrag JToolBar toolBar; // Werkzeugleiste
JButton button; // Knoepfe der Werkzeugleiste
JLabel bildLabel; // Label das im Frame erscheinen soll
public Bilderrahmen() { c = getContentPane();
MenuListener mL = new MenuListener();
menuBar = new JMenuBar();
menu = new JMenu("Bilder");
menu.setMnemonic(KeyEvent.VK_B); // kombiniert mit Alt_Taste menuItem = new JMenuItem("Hund");
menuItem.setMnemonic(KeyEvent.VK_H);
menuItem.addActionListener(mL);
menuItem.setActionCommand("dog");
menu.add(menuItem);