Swing oder AWT? - BFH

Werbung
Swing oder AWT?
Was ist das: Swing bzw. AWT
Beides sind Klassenbibliotheken mit fertig programmierten Klassen zur
Erstellung von graphischen Benutzeroberflächen mit Fenstern, Textfeldern,
Buttons etc..
AWT wurde zuerst programmiert und ist ziemlich begrenzt. Swing wurde
später hinzugefügt und baut teilweise auf AWT auf.
Swing ist wesentlich umfangreicher und flexibler als AWT.
Es gibt heutzutage eigentlich keinen Grund eine reine AWT Anwendung zu
schreiben, da es inzwischen auch möglich ist Applets mit Swing zu schreiben.
Haupterkennungsmerkmal von Swing Source-Code:
Man erkennt Swing-Programme daran, dass die Klassen der Komponenten alle
mit 'J' anfangen, während das bei AWT nicht so ist:
Beispiel für einen Button in
AWT: Button b1=new Button("bitte klicken");
Swing: JButton b1 = new JButton("bitte klicken");
Ausserdem benötigen Swing-Programme folgende Import Anweisung:
import javax.swing.* oder Ähnliches.
FH Biel, Mikro -und Medizintechnik, Java GUI-Programmierung, Peter Füss
Ein erstes Beispiel:
Zunächst ein sehr einfaches Demoprogramm welches ein Fenster mit dem
typischen Erscheinungsbild darstellt:
AWT:
Swing:
Was fällt auf?
Beide Anwendungen schliessen nicht korrekt, wenn man auf den Schliessen
Knopf 'x' klickt!
FH Biel, Mikro -und Medizintechnik, Java GUI-Programmierung, Peter Füss
Ab jetzt nur noch Swing
JFrame korrekt schliessen:
Diese Zeile einfügen
Von JFrame erben:
Bisher haben wir in der main(...) Methode ein Objekt von JFrame angelegt,
besser ist es aber von JFrame zu erben:
JFrame
Swing_Frame1
FH Biel, Mikro -und Medizintechnik, Java GUI-Programmierung, Peter Füss
In einen Frame zeichnen
Man sollte nicht direkt in einen JFrame zeichnen, statt dessen wird
eine neue Klasse 'DrawPanel' von JPanel abgeleitet, welche paint(...)
überschreibt:
public class DrawPanel extends JPanel {
public void paint(Graphics g) {
super.paint(g);
g.setFont(new Font("Arial",Font.PLAIN,24));
g.drawString("Drawing with Java is easy!", 10,
20);
g.setColor(Color.red);
g.drawRoundRect(20, 40, 60, 40, 20, 10);
g.setColor(Color.blue);
g.drawLine(50, 50, 160, 200);
}
}
g.setColor(Color.green);
g.fillOval(150, 50, 60, 100);
public class Swing_Frame extends JFrame{
//Our Custom JFrame needs a constructor
public Swing_Frame4(String title) throws HeadlessException {
super(title);
this.add(new DrawPanel());
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(300, 250);
}
public static void main(String[] args) {
JFrame frame1 = new Swing_Frame("Frame with Drawingspace");
}
frame1.setVisible(true);
}
FH Biel, Mikro -und Medizintechnik, Java GUI-Programmierung, Peter Füss
Mechanismus:
Warum braucht man eine paint(...) Methode zum Zeichnen?
Ein Programm in einer GUI-Umgebung arbeitet ereignissgesteuert.
Immer wenn das Fenster neu gezeichnet werden muss, weil es z.B. gerade
minimiert war und jetzt wieder maximiert wird, ruft das Betriebssystem die
Methode paint(...) auf.
Alles was in der Methode paint(...) programmiert ist, wird gezeichnet.
Man sollte immer in einen eigenen JPanel zeichnen, nicht in das
JFrame!
Den graphischen Kontext Graphics, welcher der 'paint(Graphics g)'
Methode übergeben wird, kann man als eine Art Zeichenblatt
betrachten. Statt eines Malstiftes hat dieser Methoden welche die
unterschiedlichsten graphischen Figuren wie Kreise, Rechtecke und
vieles mehr zeichnen können.
FH Biel, Mikro -und Medizintechnik, Java GUI-Programmierung, Peter Füss
Übung:
Schreiben Sie in die paint(...) Methode von DrawPanel ein
Programm, welches untenstehendes Ergebnis erzeugt. Die
Schneeflocken sind gefüllte Kreise mit zufälliger Grösse und
Position. Benutzen Sie dazu die Methode Math.random().
Viel Spass beim Ausprobieren!
FH Biel, Mikro -und Medizintechnik, Java GUI-Programmierung, Peter Füss
Ausschnitt aus der Swing /AWT Klassenhierarchie
JComponent
Object
Component
JLabel
Button
Label
AbstractButton
JPanel
Container
Choice
Canvas
JText
Window
List
JList
JText
JTextArea
JComboBox
JScrollBar
ScrollBar
JMenuBar
CheckBox
JOptionPane
Frame
Dialog
JFrame
JDialog
FH Biel, Mikro -und Medizintechnik, Java GUI-Programmierung, Peter Füss
JToggleButton
JCheckBox
JMenu
JMenuItem
JRadioButton
JButton
Elementare GUI-Komponenten hinzufügen
Bisher haben wir dem Hauptfenster (JFrame) nur einen JPanel
hinzugefügt. Dazu wurde die Methode add(...) von JFrame
aufgerufen. Mit dieser Methode können einem "Container"
beliebige GUI-Komponenten hinzugefügt werden. Ein Container ist
eine GUI-Komponente, welche andere GUI-Komponenten
aufnehmen kann. Die meisten Swing-Komponenten sind solche
Container -> Folie7
Jetzt werden wir einen JButton und ein JTextField hinzufügen:
Das Ergebnis schaut wohl
nicht so aus wie wir uns das
vorgestellt hatten! Der Button
ist unter dem Textfeld
verschwunden.
FH Biel, Mikro -und Medizintechnik, Java GUI-Programmierung, Peter Füss
Elementare GUI-Komponenten hinzufügen
Ganz so einfach ist es wohl doch nicht, deshalb änderen wir ein
paar Kleinigkeiten, was ein besseres Ergebnis liefert:
public class Swing_Frame5 extends JFrame {
private JButton b1,b2;
private JTextField tf;
public Swing_Frame5(String title) throws HeadlessException {
super(title);
//get reference of the ContentPane
//and set to FlowLayout
Container main=this.getContentPane();
main.setLayout(new FlowLayout());
main.add(new JTextField(" 0"));
main.add(new JButton("click me"));
}
Diese Zeile einfügen
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(300, 250);
public static void main(String[] args) {
JFrame frame1 = new Swing_Frame5("Frame with Button and Textfield");
}
}
frame1.setVisible(true);
FH Biel, Mikro -und Medizintechnik, Java GUI-Programmierung, Peter Füss
Elementare GUI-Komponenten hinzufügen
Was wurde geändert?:
Komponenten werden nicht direkt in einen JFrame gepackt, sondern in das
Contenpane des JFrames, welches man mit der Methode:getContentPane()
holen kann.
Dem Contentpane wird ein FlowLayout zugewiesen.
Layouts sind Klassen, welche die Anordnung von GUIKomponenten in Containern steuern, aber dazu mehr im Kapitel
LayoutManager.
FH Biel, Mikro -und Medizintechnik, Java GUI-Programmierung, Peter Füss
Was passiert beim Klicken auf den Button ?
So wie das Programm jetzt ist, passiert noch gar nichts wenn man
auf den Button klickt.
Wir erweitern jetzt das Programm so, dass beim Klicken auf den
Button im Textfeld der Text: "you clicked 1 times..." erscheint. Bei
jedem erneuten Klick wird die Zahl im Text um eins erhöht, somit
haben wir einen Zähler welcher die Anzahl Klicks zählt.
Für diese einfach scheinende Erweiterung muss man zunächst
verstehen wie in Java Ereignisse behandelt werden.
Dafür ist wiederum das Verständnis von Interfaces erforderlich,
deshalb im Folgenden ein kurzer theoretischer Ausflug in die
objektorientierte Programmierung:
FH Biel, Mikro -und Medizintechnik, Java GUI-Programmierung, Peter Füss
Interfaces und ActionListener
Das UML-Diagramm auf der rechten Seite zeigt
2 Klassen, wobei die Klasse Swing_Frame von
JFrame abgeleitet ist und stellt damit unser
Programmbeispiel dar. Angenommen die Klasse
Swing_Frame müsste noch von einer weiteren
Klasse erben, dann wäre das in Java nicht möglich.
JFrame
Swing_Frame
Mehrfachvererbung ist in Java nicht erlaubt!
An Stelle von Mehrfachvererbung werden in Java
Interfaces verwendet!
In der UML-Darstellung sieht das dann
so aus:
<<interface>>
ActionListener
JFrame
So etwas ist in Java nicht erlaubt!
ActionListener
implementiert
JFrame
Swing_Frame
Swing_Frame
FH Biel, Mikro -und Medizintechnik, Java GUI-Programmierung, Peter Füss
Interfaces und ActionListener
In der objektorientierten Sprache würde man hier sagen:
Swing_Frame implementiert das Interface ActionListener!
Ein Interface ist so etwas Ähnliches wie eine Klasse, mit dem
Unterschied dass davon kein Objekt erzeugt werden kann und
dass es dort nur leere Methodendeklarationen gibt. Hier ein
Beispiel für ein Interface aus der Java Standartbibliothek:
Die Definition ist gleich wie bei einer Klasse nur, dass anstatt
class, interface geschrieben wird. In diesem Beispiel gibt es
nur eine Methode die leer ist, also keinen Sourcecode beinhaltet.
FH Biel, Mikro -und Medizintechnik, Java GUI-Programmierung, Peter Füss
Interfaces und ActionListener
Eine Klasse erbt von einer Basisklasse mit dem Schlüsselwort
extends, während eine Klasse ein Interface implementiert mit
dem Schlüsselwort implements. Das UML-Diagramm weiter oben
sieht dann als Programmcode folgendermassen aus:
Programmcode der Klasse
.
.
.
.
Diese Methode muss
zwingend vorhanden
sein, da sie im Interface
definiert ist!
Nochmal: Anstatt von ActionListener zu erben wird hier das
Interface implementiert und das kann im Gegensatz zur Vererbung
von beliebig vielen Interfaces gemacht werden!
FH Biel, Mikro -und Medizintechnik, Java GUI-Programmierung, Peter Füss
Auf Button Click reagieren mit ActionListener
Damit bei einem Click auf den Button das passiert was der
Programmierer gern möchte, muss dem Button gesagt werden,
wer auf ihn hört.
Dies wird mit folgender Programmzeile gemacht:
wobei b ein Objekt von JButton ist. Da diese Programmzeile in
unserer Klasse Swing_Frame steht und wir this übergeben,
sendet der Button die Klick-Nachricht an den Frame, in dem er
sich befindet, also an Swing_Frame. Dies geht aber nur, wenn
Swing_Frame vom Typ ActionListener ist. Diese Vorraussetzung
wurde geschaffen wie in der vorigen Folie zu sehen ist.
JFrame
extends
Swing_Frame
"click me" sendet KlickEreignis an ActionListner
Swing_Frame und ruft dort
actionPerformed(...) auf
<<ActionListener>>
implements
Swing_Frame implementiert
ActionListener und ist somit
vom Typ ActionListener!
+ actionPerformed(ActionEvent e)
FH Biel, Mikro -und Medizintechnik, Java GUI-Programmierung, Peter Füss
actionPerformed(...) auscodieren:
Hier nun die komplette
Klassendefinition:
public class Swing_Frame6 extends JFrame
implements ActionListener {
private JButton b;
private JTextField tf;
private int nClicks=0; //counts the number of buttonclicks
public Swing_Frame6(String title) throws HeadlessException {
super(title);
//get Contentpane and set Layoutmanager
Container contPane=getContentPane();
contPane.setLayout(new FlowLayout());
//create GUI-Elements...
b=new JButton("click me");
tf=new JTextField("you clicked
0 times");
//...and add them to Contentpane
contPane.add(b);
contPane.add(tf);
Nach dem ersten klicken auf 'click me':
//Button notifies a click to his own JFrame
b.addActionListener(this);
}
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(300, 250);
//actionPerformed(...) is called whenever an
//action in this Frame is done.
//In this case when the Button is clicked, it sends a
//message to this JFrame which is an ActionListener
public void actionPerformed(ActionEvent e) {
if(e.getActionCommand()=="click me") {
nClicks++;
tf.setText("you clicked "+nClicks+" times ");
}
}
Nach dem zweiten klicken auf 'click me':
public static void main(String[] args) {
JFrame frame1 = new Swing_Frame6(
"Frame with Button and Textfield");
}
}
FH Biel, Mikro -und Medizintechnik, Java GUI-Programmierung, Peter Füss
frame1.setVisible(true);
Übersicht der meisten Java Listener
FH Biel, Mikro -und Medizintechnik, Java GUI-Programmierung, Peter Füss
Beispiel mit MouseListener
public class DrawPanelWithMouseListener extends JPanel
implements MouseListener {
private Rectangle r;
private Color baseColor=Color.gray;
private Color currentColor;
public DrawPanelWithMouseListener() {
super();
r=new Rectangle(100,100,50,50);
currentColor=baseColor;
this.addMouseListener(this);
}
Bei einem Klick in
das Rechteck wird
es rot, ausserhalb
davon grau
public void paint(Graphics g) {
super.paint(g);
g.setColor(currentColor);
g.fillRect(r.x, r.y, r.width, r.height);
}
public void mouseClicked(MouseEvent e) {
if(r.contains(e.getPoint())) {
this.currentColor=Color.red;
}else {
this.currentColor=baseColor;
}
this.repaint();
}
public void mouseExited(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
public void mouseReleased(MouseEvent e) {
}
}
}
FH Biel, Mikro -und Medizintechnik, Java GUI-Programmierung, Peter Füss
Beschreibung:
Das DrawPanelWithMouseListener implementiert einen
MouseListener dafür muss es die Methoden
'mouseClicked(...)','mousePressed(...)','mouseEntered(...),
etc.
enthalten, insgesamt sind es fünf.
Da wir für das Programm vorläufig nur einen MouseClick abfragen
müssen, sind alle Methoden ausser 'mouseClicked(...)' leer.
In 'mouseClicked(MouseEvent e)' kann aus dem Parameter e mit
der Methode e.getPoint() die aktuelle Position des Mausezeigers
ermittelt werden.
In der Zeile if(r.contains(e.getPoint()) wird geprüft, ob der
Mauszeiger innerhalb des Rechtecks ist. Demnach wird dann die
Farbe auf rot oder grau gesetzt.
FH Biel, Mikro -und Medizintechnik, Java GUI-Programmierung, Peter Füss
Interface MouseListener
Hier der Code von MouseListener wie er in der Java
Standard-Klassenbibliothek definiert ist:
public interface MouseListener extends
EventListener {
Wie man sieht, können sogar Interfaces
vererbt werden, sämtliche Listener sind in
Java von EventListener abgeleitet.
public void mouseClicked(MouseEvent e);
public void mousePressed(MouseEvent e);
public void mouseReleased(MouseEvent e);
public void mouseEntered(MouseEvent e);
public void mouseExited(MouseEvent e);
}
FH Biel, Mikro -und Medizintechnik, Java GUI-Programmierung, Peter Füss
Übersichtlicher mit Adapter
Ein Listener kann auch in einer anderen Klasse implementiert
werden, als in derjenigen in der das Event erzeugt wird:
public class MouseListenerExtern implements MouseListener {
DrawPanelWithMouseAdapter sender;
public MouseListenerExtern(DrawPanelWithMouseAdapter sender) {
this.sender = sender;
}
public void mouseClicked(MouseEvent e) {
if(sender.getRectangle().contains(e.getPoint())) {
sender.setColor(Color.red);
}else {
sender.resetColor();
}
Der Methode addMouseListener in DrawPanel... muss
sender.repaint();
}
jetzt allerdings dieser Listener übergeben werden!:
public void mouseEntered(MouseEvent e) {
}
addMouseListener(new MouseListenerExtern(this));
public void mouseExited(MouseEvent e) {
}
Der sender wird gebraucht, da der Listener auf das
Rechteck und die Farbe von DrawPanel... zugreifen
können muss.
public void mousePressed(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
}
}
FH Biel, Mikro -und Medizintechnik, Java GUI-Programmierung, Peter Füss
Übersichtlicher mit Adapter
Wenn man nun den MouseListener nicht implementiert, sondern
als Klasse von MouseAdapter ableitet, müssen nur die Methoden
geschrieben werden die man braucht:
public class MouseHandler extends MouseAdapter{
DrawPanelWithMouseAdapter sender;
public MouseHandler(DrawPanelWithMouseAdapter sender) {
this.sender=sender;
}
public void mouseClicked(MouseEvent e) {
}
}
if(sender.getRectangle().contains(e.getPoint())) {
sender.setColor(Color.red);
}else {
sender.resetColor();
}
sender.repaint();
Dies funktioniert mit einem einfachen Trick:
MouseAdapter implementiert MouseListener und damit alle seine
Methoden. In der von MouseAdapter abgeleiteten Klasse wird einfach
die mouseClicked(...) Methode überschrieben. MouseAdapter ist in der
Java-Standardbibliothek vordefiniert! Diese Adapter gibt es für viele
andere Listener auch. siehe Folie 17
FH Biel, Mikro -und Medizintechnik, Java GUI-Programmierung, Peter Füss
Herunterladen