.: java - grafische programmierung :.
 
abyter.de \\ workshops

<Fortsetzung von letzter Seite

Buttons
Bis jetzt konnte der Benutzer recht wenig machen, er konnte sich Schrift, Linien und Rechtecke ansehen. Am Ende konnte er das Fenster auch noch schließen, er konnte jedoch keine Aktionen durchführen. Damit der Benutzer auch mal was machen kann, bekommt unser Programm nun einen Button.
Natürlich kommt der Button nicht von selbst, man muss ihn erst einmal auf dem Frame hinzufügen. Dafür gibt es die add-Methode des Frames. Jetzt hätten wir aber wieder das gleiche Problem wie beim Schließen-Button beim Frame. Es passiert nichts! Also machen wir es doch so wie beim Frame: Wird setzen einen Listener ein! Diesmal jedoch nicht den WindowListener, sondern den ActionListener. Dieser ist praktisch genauso aufgebaut wie der WindowListener: addActionListener(ActionListener);
Wie schon beim WindowListener braucht die Methode ein Objekt des Interfaces ActionListener. Dieses Interface bietet als einzige Methode actionPerformed an.
Wir schauen uns also wieder den Quelltext zum besseren Verständnis an:

import java.awt.*;

public class Fenster6 extends Frame
{
private Button btnBeenden = new Button("Beenden");
private MyWindowListener myWindowListener = new MyWindowListener();
private MyActionListener myActionListener = new MyActionListener();

public Fenster6()
{
super("Unser sechstes Fenster...");
this.setSize(400,100);
this.add(this.btnBeenden);
this.show();
this.addWindowListener(myWindowListener);
this.btnBeenden.addActionListener(myActionListener);
}

public static void main(String args[])
{
Fenster6 f = new Fenster6();
}
}
MyWindowListener.java
import java.awt.event.*;
public class MyWindowListener extends WindowAdapter
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
}
MyActionListener.java
import java.awt.event.*;
public class MyActionListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
System.exit(0);
}
}

In der Klasse MyActionListener sollte einem ein ungewöhnliches Schlüsselwort auffallen: implements. implements ist das Gegenstück der Interfaces zum extends der Klassen bei der Vererbung.
Wenn du das Programm ausführst, entdeckt man jedoch schon das nächste Problem:

Fenster mit Button

Der Button füllt das ganze Fenster aus! Diesem Problem wollen wir uns nun widmen!

Layout-Manager
Wir haben gerade selbst gesehen was passiert wenn man keine absolute Positionierung (mit Pixelangaben) macht. Der Button füllt den ganzen Frame aus. Aber mal zugegeben, willst du bei jedem Button immer herum probieren wie groß er sein soll und die Pixelangaben dann ändern und jedes Mal auch noch langwierig kompilieren? Das ist schon ganz schön umständlich mit den Pixeln! Aber so ein ganzes Frame für nur einen Button ist reinste Verschwendung.
Aber wie immer gibt es in Java auch dafür eine komfortable Lösung: die Layout-Manager. Die Layout-Manager wenden Regeln zur Positionierung und Dimensionierung der Buttons an. Im Package awt gibt es zwar 5 Layout-Manager, ich möchte davon jedoch nur die drei wichtigsten behandeln. Und zwar FlowLayout, BorderLayout und GridLayout.

FlowLayout
Dieser Layout-Manager ordnet die Komponenten in Zeilen von links nach rechts an. Wenn eine Zeile voll ist, wird die nächste Komponente in der nächsten Zeile darunter angeordnet. FlowLayout setzt die Größe der Komponenten auf ein Minimum. Der FlowLayout-Manager hat folgenden Konstruktor: FlowLayout(int ausrichtung, int horizAbstand, int vertAbstand)
Wobei eigentlich sämtliche Parameter optional sind. Wenn nämlich nichts angegeben ist, werden die Komponenten zentriert angeordnet und die Abstände sowohl horizontal als auch vertikal auf 5 Pixel gesetzt. Abstände werden verständlicherweise in Pixel angegeben, bei der Ausrichtung gibt es folgende Wahlmöglichkeiten bestehend aus statischen Konstanten: FlowLayout.LEFT, FlowLayout.RIGHT und FlowLayout.CENTER
Ich habe mal folgenden Quelltext zur Verdeutlichung anzubieten:

import java.awt.*;

public class Fenster7 extends Frame
{
private FlowLayout myLayout = new FlowLayout(FlowLayout.LEFT);
private MyWindowListener myWindowListener = new MyWindowListener();
private MyActionListener myActionListener = new MyActionListener();
private Button btn1 = new Button("1");
private Button btn2 = new Button("2");
private Button btn3 = new Button("3");
private Button btn4 = new Button("4");

public Fenster7()
{
super("Unser siebentes Fenster...");
this.setLayout(myLayout);
this.setSize(200,100);
this.add(this.btn1);
this.add(this.btn2);
this.add(this.btn3);
this.add(this.btn4);
this.show();
this.addWindowListener(this.myWindowListener);
this.btn1.addActionListener(this.myActionListener);
this.btn2.addActionListener(this.myActionListener);
this.btn3.addActionListener(this.myActionListener);
this.btn4.addActionListener(this.myActionListener);
}

public static void main(String args[])
{
Fenster7 f = new Fenster7();
}
}
MyWindowListener.java
import java.awt.event.*;

public class MyWindowListener extends WindowAdapter
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
}
MyActionListener.java
import java.awt.event.*;
public class MyActionListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
int wert = integer.parseInt(e.getActionCommand());
switch(wert)
{
case 1: System.out.println("Button 1"); break;
case 2: System.out.println("Button 2"); break;
case 3: System.out.println("Button 3"); break;
case 4: System.out.println("Button 4"); break;
}
}
}

In der main-Methode wird nur das Fenster erzeugt, das Aussehen wird im Konstruktor festgelegt. Der Aufruf des Layout-Managers funktioniert mit setLayout. Erst danach werden die einzelnen Komponenten dem Frame-Container hinzugefügt.
Da alle Buttons mit dem gleichen ActionListener-Objekt verbunden sind, muss man in der MyActionListener-Klasse eine Unterscheidung mittels einer switch-Auswahlabfrage durchführen. Die dafür nötigen Daten liefert das ActionEvent-Objekt aus der actionPerformed-Methode. Erst danach steht fest welcher Button der Auslöser war.
Jede grafische Komponente hat ein Attribut mit dem Namen actionCommand, wenn keine Änderung daran vorgenommen wurde stimmt dieses Attribut mit der Beschriftung überein. So können wir mit der Anweisung getActionCommand, dieses Attribut aus dem Auslöser auslesen. Nach einer Umwandlung des Strings in einen Integerwert kann man ihn als Selektor einsetzen.
Der Frame sieht so aus:

Fenster nach dem FlowLayout

BorderLayout
Das BorderLayout orientiert sich an den Rändern, die durch die Himmelsrichtungen bezeichnet werden. Aber natürlich gibt es auch eine Mitte. Mit dem BorderLayout lassen sich maximal fünf Komponenten platzieren.
Das BorderLayout passt die Komponentengröße der Framegröße an. Die BorderLayout-Anweisung ist folgendermaßen aufgebaut: BorderLayout(int horizAbstand, int vertAbstand)
Die Abstände sind wieder optional, wird also nichts angegeben, wählt der Compiler automatisch den Abstand 0 Pixel. Es wird also kein Abstand gelassen, wer dies verhindern will, der muss die Abstände angeben. Da die Position der Komponente angegeben werden muss, ist es nötig die add-Methode anzupassen. Sie muss nun so aussehen:
add(Component komponentennamen, int pos)

In der Praxis müsste die Anweisung also so aussehen: this.add(myButton, BorderLayout.CENTER). Hier sieht man schon eine der Positionsangaben im Einsatz; die anderen sehen so aus: BorderLayout.EAST, WEST, NORTH, SOUTH
Ich möchte diesmal nur die Quellcodedatei angeben, die sich gegenüber dem FlowLayout auch geändert hat. Wer das Beispiel nachvollziehen will, muss einfach noch die Dateien MyWindowListener.java und MyActionListener.java aus dem vorherigen Beispiel abschreiben (oder in den Workspace einbinden). Hier aber nun der Quelltext:

import java.awt.*;
public class Fenster8 extends Frame
{
private BorderLayout borderLayout = new BorderLayout();
private MyWindowListener myWindowListener = new MyWindowListener();
private MyActionListener myActionListener = new MyActionListener();
private Button btnNorth = new Button("1");
private Button btnSouth = new Button("2");
private Button btnEast = new Button("3");
private Button btnWest = new Button("4");

public Fenster8()
{
super("Unser achtes Fenster...");
this.setLayout(borderLayout);
this.setSize(300,300);
this.add(btnNorth, BorderLayout.NORTH);
this.add(btnSouth, BorderLayout.SOUTH);
this.add(btnEast, BorderLayout.EAST);
this.add(btnWest, BorderLayout.WEST);
this.show();
this.addWindowListener(this.myWindowListener);
this.btnNorth.addActionListener(this.myActionListener);
this.btnSouth.addActionListener(this.myActionListener);
this.btnEast.addActionListener(this.myActionListener);
this.btnWest.addActionListener(this.myActionListener);
}

public static void main(String args[])
{
Fenster8 f = new Fenster8();
}
}

So sieht das BorderLayout aus:

Fenster nach dem BorderLayout

GridLayout
Das GridLayout ordnet die Komponenten in Spalte von links nach rechts und die Zeilen von oben nach unten. Der Konstruktor ist folgendermaßen aufgebaut: GridLayout(int zeilen, int spalten, int hAbstand, int vAbstand)
Die Abstände sind wieder optional. Wenn man ENTWEDER für zeilen ODER für spalten als Wert '0' eingibt, so werden die Spalten oder Zeilen beliebig gefüllt. Es ist jedoch wichtig, dass immer nur einer der Parameter '0' als Wert hat.
Der Hauptquelltext sieht so aus:

import java.awt.*;
public class Fenster9 extends Frame
{
private GridLayout myGridLayout = new GridLayout(2,0);
private MyWindowListener myWindowListener = new MyWindowListener();
private MyActionListener myActionListener = new MyActionListener();
private Button btn1 = new Button("1");
private Button btn2 = new Button("2");
private Button btn3 = new Button("3");
private Button btn4 = new Button("4");

public Fenster9()
{
super("Unser neuntes Fenster...");
this.setLayout(borderLayout);
this.setSize(300,300);
this.add(this.btn1);
this.add(this.btn2);
this.add(this.btn3);
this.add(this.btn4);
this.show();
this.addWindowListener(this.myWindowListener);
this.btn1.addActionListener(this.myActionListener);
this.btn2.addActionListener(this.myActionListener);
this.btn3.addActionListener(this.myActionListener);
this.btn4.addActionListener(this.myActionListener);
}

public static void main(String args[])
{
Fenster9 f = new Fenster9();
}
}

Unser GridLayout-Fenster sieht dann so aus:

Fenster nach dem GridLayout

Panels
Was ist die logische Konsequenz aus allen drei vorherigen Layout-Managern: Am besten wäre es, wenn man sie kombinieren könnte! Ja, und genau das wollen wir nun tun. Mit Panels lassen sich die vorherigen Layout-Manager kombinieren um ein individuelles Layout zu entwerfen.
Ein Panel dient als Container-Objekt und ist selbst eine Komponente. So lassen sich mehrere Panels auf dem Frame wie Komponenten anordnen, bei dem jedoch jedes Panel seinen eigenen Layoutmanager hat. Der Panel-Konstruktor sieht so aus:
Panel(LayoutManager layout)

Aber erst wenn man den Haupt-Quelltext gesehen hat, sieht man wie Panels wirklich arbeiten:

import java.awt.*;
public class Panel1 extends Frame
{
private MyWindowListener myWindowListener = new MyWindowListener();
private MyActionListener myActionListener = new MyActionListener();
private Button btn1 = new Button("1");
private Button btn2 = new Button("2");
private Button btn3 = new Button("3");
private Button btn4 = new Button("4");
private Button btn5 = new Button("5");
private Button btn6 = new Button("6");
private Panel pnlNorth = new Panel(new BorderLayout());
private Panel pnlCenter = new Panel(new GridLayout(1,2));
private Panel pnlSouth = new Panel(new FlowLayout(FlowLayout.RIGHT));
public Panel1()
{
super("Unser Panel-Fenster...");
this.setSize(300,300);
this.pnlNorth.add(btn1, BorderLayout.WEST);
this.pnlNorth.add(btn2, BorderLayout.EAST);
this.pnlCenter.add(btn3);
this.pnlCenter.add(btn4);
this.pnlSouth.add(btn5);
this.pnlSouth.add(btn6);
this.add(pnlNorth, BorderLayout.NORTH);
this.add(pnlCenter, BorderLayout.CENTER);
this.add(pnlSouth, BorderLayout.SOUTH);
this.show();
this.addWindowListener(this.myWindowListener);
this.btn1.addActionListener(this.myActionListener);
this.btn2.addActionListener(this.myActionListener);
this.btn3.addActionListener(this.myActionListener);
this.btn4.addActionListener(this.myActionListener);
}

public static void main(String args[])
{
Panel1 p = new Panel1();
}
}

Ein Bild des Frames zeigt wie unsere Panels aussehen:

Fenster mit Panels

Wir erzeugen drei Panels die wir mittels BorderLayout übereinander anordnen. Im ersten Panel erzeugen wir ein BorderLayout, im zweiten ein GridLayout und im letzten ein FlowLayout. Schon ist unser Panel-Fenster fertig. Sieht doch gar nicht so schlecht aus!

Weiter auf der nächsten Seite >

Related Workshops: Allgemeines \\ Java Einführung \\ Arbeit mit dem JCreator \\ Programmieren mit Java \\ Programmiergrundlagen \\ Klassen-Grundlagen \\ Datenbankprogrammierung
Related Files: JCreator LE

Workshop als PDF

<Zurück

© by www.abyter.de (Martin Monshausen)