 |
Swing |
|
| Swing
|
Im
Einführungskurs haben Sie einfache Grafik - Möglichkeiten kennengelernt.
Swing bietet professionelle GUI
Elemente.
Und bereits das Fenster, das wir brauchen ist ein "Swing Fenster" namens
JFrame.
Dieses Fenster
ist am besten eine Klasse für sich in einer eigenen
Datei. Also gehen wir vor wie meist, wenn unsere Programme in einem
Fenster ablaufen sollen: Wir machen zwei Klassen in
zwei Dateien: Die eine enthält die Methode main() und
in dieser wird eine Instanz der zweiten Klasse, der Fenster - Klasse,
gemacht:
- Erstellen Sie
ein neues Projekt, z.B. namens SwingTesten.
- Erstellen Sie
zwei neue Klassen, z.B. namens SwingTesten und SwingFrame.
- Die Klasse SwingTesten sieht so aus:
public class SwingTesten {
public static void main(String[] args) {
SwingFrame frame = new SwingFrame();
frame.show();
}
}
- Die Klasse SwingFrame sieht so aus:
import javax.swing.JFrame;
public class SwingFrame extends JFrame {
}
|
|
| Hallo Welt |
- Starten Sie das
Projekt und seien Sie nicht erstaunt über das schnuckelig kleine Fensterchen
- siehe rechts. Das Fenster hat noch keine Grösse, es besteht nur aus
dem oberen Balken! Schritt für Schritt soll nun das Fenster mit Inhalt
gefüllt werden.
|
 |
| Fenstergrösse |
- Fenstergrösse: Ergänzen
Sie SwingFrame mit einem Konstruktor, in welchem die Methode setSize()
die Fenstergrösse festlegt:
SwingFrame(){
this.setSize(new Dimension(200,200));
}
- Testen Sie - das
Fenster sollte etwa so wie das rechts aussehen.
|
 |
| Fenstertitel |
- Fenstertitel:
Die Methode this.setTitle("Mein
Testfenster"); setzt einen Titel in
den Fensterbalken. Am besten rufen Sie die Methode auf nach setSize().
- Testen Sie! Siehe
rechts.
|
 |
| Taste |
- Taste: Jetzt
soll das Fenster einen Inhalt kriegen: Wir machen
eine Taste, die man drücken kann. Tasten in Swing heissen JButton:
Sie machen eine
Instanz von JButton und fügen Sie dann mit der Methode add() der ContentPane
zu. Der Konstruktor sieht dann so aus:
SwingFrame(){
this.setSize(new Dimension(200,200));
this.setTitle("Mein Testfenster");
JButton
taste = new JButton("Drück' mich!");
this.add(taste);
}
- Testen Sie wieder!
Beachten Sie:
- Die Taste füllt das ganze Fenster.
- Ein Tastendruck bewirkt noch nichts.
- Bei allen Swing Klassen beginnt der Name mit J: JFrame, JButton,
...
|
 |
| Events |
- Damit
der Tastendruck etwas bewirkt, brauchen wir einen "Listener",
also eine Einrichtung, welche einen Tastendruck (einen Event) registrieren
kann (siehe Kapitel Events!). Die ganze Fensterklasse sieht dann so aus:
import java.awt.Container;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
public class SwingFrame extends
JFrame {
SwingFrame()
{
this.setSize(new
Dimension(200, 200));
this.setTitle("Mein
Testfenster");
JButton
taste = new JButton("Drück' mich!");
taste.addActionListener(new
ButtonListener());
this.add(taste);
}
class ButtonListener
implements ActionListener {
public
void actionPerformed(ActionEvent e) {
System.out.println("Taste
gedrückt!");
}
}
}
Sie sehen, dass wir
der Taste mit der Methode addActionListener() einen Listener zufügen.
Den Listener machen wir selber und nennen ihn ButtonListener. Damit
die Klasse ButtonListener
ein Listener ist, müssen wir das Interface ActionListener implementieren.
Die Klasse ButtonListener würde normalerweise in einer eigenen Datei
stehen. Hier ist es aber günstiger, sie als innere Klasse in der Klasse
SwingFrame azu deklarieren.
Ein ActionListener muss eine Methode astionPerformed() haben. Diese wird
aufgerufen, wenn der
Event stattfindet (wenn also die Taste gedrückt wird) und sie sagt,
was in diesem Fall geschehen soll: Hier wird zum Test ein Text auf die
Konsole geschrieben.
|
|
| Label |
- Wir möchten,
dass alles im gleichen Fenster erscheint, auch der Text, den wir via
Taste produzieren. Eine Ausgabe im Fenster machen wir in einem JLabel:
JLabel label
= new JLabel("Taste noch nicht gedrückt");
this.add(label);
Übersetzen Sie und führen Sie aus - hoppla, das Label erscheint, dafür
ist die Taste weg! Das kommt daher, dass in Swing der Standard - Layout nicht
ein FlowLayout, sondern ein BorderLayout ist. Und bei diesem
gehen standardmässig die GUI Elemente in den Bereich CENTER (Mitte). Daneben
gibt es die Bereiche NORTH (oben), SOUTH (unten), EAST (rechts) und WEST (links).
- Setzen Sie die Taste
oben und das Label unten. Für die Taste sieht das so aus:
this.add(taste,BorderLayout.NORTH);
- jetzt sollten Sie Taste und Label sehen.
- Das Drücken
der Taste soll jetzt einen andern Text im Label ergeben: Ersetzen Sie
in actionPerformed() System.out.println() durch:
label.setText("danke!");
Es gibt noch ein kleines Problem: Wenn Sie label hier brauchen, muss es als
Klassenvariable ausserhalb des Konstruktors deklariert sein, sie müssen
also Deklaration und erzeugen der Instanz trennen!
|
 |
| ToolTip |
- Noch ein kleiner
Gag: Sie können sogenannte ToolTips setzen, also
Texte, die erscheinen, wenn man über ein GUI Element fährt
mit der Maus:
taste.setToolTipText("Drücken
Sie diese Wundertaste!");
- testen Sie auch das!
|
|
| ImageIcon |
- Und ein
zweiter kleiner Gag, der zeigen soll, dass Swing fast unbegrenzt viele
Möglichkeiten bietet: Auf der Taste soll ein Bild zu sehen sein:
ImageIcon icon = new
ImageIcon("wappen.gif");
JButton taste = new JButton("drück mich!",icon);
Die Bilddatei wappen.gif, welche als Icon
verwendet wird, muss im Ordner sein, in welchem sich SwingFrame.class befindet.
|
 |
| Slider |
Als
Beispiel für ein etwas raffiniereteres GUI Element sollen Sie Ihr Programm
noch mit einem Schieberegler ergänzen. JSlider ist
ein Schieberegler.
- Ein Beispiel wie
Sie Ihr Programm mit einem JSlider ergänzen können finden Sie hier.
|
 |
| Dokumentation |
Um
sich eine Übersicht über die Möglichkeiten von Swing zu verschaffen
sehen Sie sich am besten die Dokumentation an:
- Öffnen Sie im Browser
die Datei index.html im Ordner C:\j2sdk1.4.2_08\docs oder
ähnlich. Klicken Sie auf "Guide to Features"
und dort unter "Java
Foundation Classes" auf "Project Swing Components".
Sie sehen, dass sich
Swing im Package javax.swing befindet, wobei es aber
mehrere Unterpackages gibt. Am besten klicken Sie auf das Package javax.swing
und sehen sich
die "Class Summary" an. Interessante Klassen
sind z.B. JTextField und JTextArea (Textein- und ausgabe), JMenu, JRadioButton,
JChechBox, ....
|
|
| Zeichnung |
Nach dieser allgemeinen Einführung in Swing wollen wir eine
kleine Anwendung machen: In einem Bereich des Layout (CENTER) wollen wir
eine Zeichnung erstellen.
- Erzeugen Sie dazu
zuerst ein neues Projekt (das ergibt eine gute Repetition zum letzten
Mal!), z.B. mit dem Namen Zeichnung.
- Wieder enthält
das Projekt zwei Klassen: Die mit der main() - Methode und die mit
dem JFrame:
public class Zeichnung {
public static void main(String[] args)
{
ZeichnungFrame frame = new ZeichnungFrame();
frame.show();
}
}
und
import javax.swing.JFrame;
public class ZeichnungFrame extends JFrame {
}
- Testen Sie, ob
dieses "leere" Pojekt funktioniert.
- Machen Sie das
Fenster z.B. 500 mal 500 Pixel gross und setzen Sie eine Taste in
den Layoutbereich NORTH und testen Sie.
- .
|
|
| Innere Klasse |
Den
Bereich, in welchem wir zeichnen wollen, erstellen wir als neue Klasse.
Weil sie
nur von unserer Klasse ZeichnungFrame gebraucht
wird, "verpacken" wir sie in diese hinein (das haben wir früher übrigens
auch mit dem ButtonListener so gemacht!). Man nennt dies eine innere
Klasse, also eine Klasse in einer Klasse:
class Bereich extends JComponent {
public void paint(Graphics g) {
g.drawLine(0,0,this.getHeight(), this.getWidth());
}
}
- Sie sehen, dass
die Klasse JComponent eine paint() Methode hat, welche wir überschreiben
und damit zeichnen können. Ergänzen Sie Ihr Programm mit dieser Klasse,
am besten definieren Sie diese vor dem Konstruktor. Im Konstruktor,
nach der Taste können Sie nun eine Instanz erstellen und das geänderte
Programm testen:
Bereich bereich = new Bereich();
this.add(bereich);
- Ergänzen
Sie nun Ihr Programm mit einem Listener für die Taste, der erst
mal irgendwas auf die Konsole schreibt, wenn die Taste gedrückt
wird.
- Und jetzt soll der
Klick auf die Taste bewirken, dass irgendetwas anderes (z.B. ein Quadrat)
gezeichnet wird.
Tips:
- Die Methode repaint() bewirkt, dass paint() ausgeführt wird.
-Im Kapitel 5. Grafik des Einführungskurses finden Sie weitere Angaben
zur Grafik, damit Sie weiter spielen können.
|
|
| Zufall |
Die Zeichnung (z.B. ein Quadrat) soll nun nach Tastenklick
an einer zufälligen Stelle im Fenster erscheinen. Zufallszahlen liefert
uns die Methode Math.random():
- Berechnen Sie
also in der Methode actionPerformed() zufällige Koordinaten und verwenden
Sie diese dann um in paint() zu zeichnen. Beachten Sie, dass die
Koordinaten an mehreren Orten bekannt sein müssen, deklarieren Sie
sie also in der Klasse ZeichnungFrame. Für die x-Koordinate könnte
das so aussehen:
x = (int) ((Math.random()*bereich.getWidth()));
- .
|
 |
| Animation |
- Für eine Animation (Objekt soll sich bewegen) brauchen Sie
einen Thread. Das geht z.B. so, dass Sie für ZeichnungFrame das Interface
Runnable implementieren:
public class ZeichnungFrame
extends JFrame implements Runnable
dann im Konstruktor einen Thread erzeugen:
t = new Thread(this);
und diesen mit der Methode actionPerformed() starten:
t.start();
Was geschehen soll wenn der Thread läuft, bestimmen Sie in der methode
run(). Diese sieht bei mir so aus:
public void run() {
while (running) {
x = (int) ((Math.random() * (bereich.getWidth() - groesse)));
y = (int) ((Math.random() * (bereich.getHeight() - groesse)));
repaint();
try {
Thread.sleep(zeitschritt);
} catch (InterruptedException e) {
System.out.println("Thread wurde unterbrochen");
e.printStackTrace();
}
}
}
Ich habe eine boolean running eingeführt, welche true ist, währenddem
die Animation läuft ("Start" Taste wurde gedrückt) und false ist, wenn
man getroffen hat. Die Berechnung der Koordinaten habe ich jetzt von
der actionPerformed() in die run() Methode gezügelt.
.
|
|
| Mouse Event |
- Jetzt sollte noch auf einen Klick auf das Objekt reagiert
werden. Dazu implementieren wir auch noch den MouseListener:
public class ZeichnungFrame extends JFrame implements Runnable,
MouseListener {
fügen ihn dem Zeichnungsbereich zu:
bereich.addMouseListener(this);
und schreiben die Methoden, wobei alle ausser mousePressed() leer sind:
public void mousePressed(MouseEvent e) {
if ((e.getX() > x) & (e.getX() < (x + groesse)) & (e.getY() > y)
& (e.getY() < (y + groesse))) {
erwischt = true;
}
}
Mit dem if prüfen wir ob in den Bereich des Objektes geklickt wurde.
.
Die fertige Klasse ZeichnungFrame finden Sie hier.
|
|
| |
- Ein Beispiel für
das Verstellen des "look and feel" finden Sie hier.
:
|
|
| |
|
|