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

< Fortsetzung von letzter Seite

List
Das List-Objekt ist der vorher behandelten Choice-Komponente nicht unähnlich. Der Unterschied besteht darin, dass bei List immer mehrere Einträge sichtbar sind. Sind mehr Einträge in der List als angezeigt werden können, so werden die restlichen nach dem Scrollen sichtbar.
Der Konstruktor sieht so aus: List(int zeilen, boolean multipleMode)
Wenn die Zahl der Zeilen nicht angegeben wird, ist die Größe allein durch den Layout-Manager bestimmt. Mit dem Parameter multipleMode kann festgelegt werden, ob mehrere Einträge gleichzeitig ausgewählt sein dürfen.
Hier nun der Quelltext unseres Beispielprogramms:

import java.awt.*;
public class Liste extends Frame
{
public List lstNamen = new List(10,true);
public Button btnHinzu = new Button(">>");
public TextArea taNamen= new TextArea(10,20);
private MyActionListener myActionListener = new MyActionListener(this);

public Liste()
{
super("Liste");
this.lstNamen.add("Müller");
this.lstNamen.add("Meier");
this.lstNamen.add("Schulze");
this.lstNamen.add("Kohler");
this.lstNamen.add("Mink");
this.lstNamen.add("Klemm");
this.lstNamen.add("Schmidt");
this.lstNamen.add("Welter");
this.lstNamen.add("Siegel");
this.lstNamen.add("Fohler");
this.lstNamen.add("Ryan");
this.lstNamen.add("Gross");
this.lstNamen.add("Rohr");
this.lstNamen.add("Schott");
this.add(this.lstNamen, BorderLayout.WEST);
this.add(this.btnHinzu, BorderLayout.CENTER);
this.add(this.taNamen, BorderLayout.EAST);
this.pack();
this.show();
this.addWindowListener(new MyWindowListener());
this.btnHinzu.addActionListener(myActionListener);
}

public static void main(String args[])
{
Liste f = new Liste();
}
}
MyActionListener.java
import java.awt.event.*;
public class MyActionListener implements ActionListener
{
public Liste f;
public MyActionListener(Liste f)
{
this.f=f;
}

public void actionPerformed(ActionEvent e)
{
String feld[]=f.lstNamen.getSelectedItems();
for(int i= 0; i<feld.length; i++)
f.taNamen.append(feld[i]+"\n");
f.show();
}
}

Wird der Button gedrückt, werden alle selektierten Einträge der Liste über die Methode getSelectedItem() in ein String-Array geschrieben, das danach über eine Schleife in die TextArea hinzugefügt wird.
So sieht unser Machwerk dann aus:

Liste im Fenster

Menüs
Natürlich gibt es auch die Möglichkeit ein Menü anzulegen. Mit folgendem Konstruktor wird in Java ein Menü angelegt:
Menu(String label, boolean beweglich)
Zusätzliche Menüpunkte können auch noch zur Laufzeit mit der Methode setLabel() hinzugefügt werden. Der Parameter beweglich ist nur unter UNIX einsetzbar, da Windows keine beweglichen Menüs, die an eine beliebige Stelle gezogen werden können, unterstützt.
Soll sich das Menü auch ausklappen lassen, dann muss man die MenuBar einsetzen. Folgender Konstruktor erzeugt eine leere MenuBar: MenuBar menueZeile = new MenuBar();
Als Menüpunkte kommen normale MenuItems infrage oder aber CheckboxMenuItems, die zusätzlich ein Häkchen vor dem Menüpunkt anzeigen können. Die Konstrutoren sehen so aus:
MenuItem(String label, MenuShortcut taste)
CheckboxMenuItem(String label, boolean status)

Beim MenuItem kann man mit dem Parameter taste eine Tastenkombination (z.B. [Alt]+[D] für Datei) angeben, wird diese gedrückt, wird der Menüpunkt ausgewählt. Diese Tastenkombination (auch Acceleration-Key genannt) wird nach folgendem Schema angegeben KeyEvent.VK_D
Also VK zuzüglich der Bezeichnung der entsprechenden Taste, VK repräsentiert also die [Alt]-Taste (beim Mac die Command-Taste).
Beim CheckboxMenuItem kann man mit dem Parameter status festlegen ob bereits das Häkchen vor dem Menüpunkt gesetzt worden ist.
Ein Klick auf einen Menüeintrag ruft (wie beim Button) ein ActionEvent hervor, darum ist das Menü auch so zu behandeln wie der Button. Ein CheckboxMenuItem erzeugt ein ItemEvent, wenn ein Häkchen gesetzt wurde.
So sieht der Quelltext unseres Beispielprogramms aus:

import java.awt.*;
import java.awt.event.*;
public class Editor3 extends Frame
{
public TextArea taText = new TextArea(15,50);
public MenuBar menuBar = new MenuBar();
public Menu menuDatei = new Menu("Datei");
public MenuItem miOpen = new MenuItem("Öffnen...", new MenuShortcut(KeyEvent.VK_O));
public MenuItem miSave = new MenuItem("Speichern...", new MenuShortcut(KeyEvent.VK_S));
public MenuItem miClose = new MenuItem("Schließen", new MenuShortcut(KeyEvent.VK_C));
public MenuItem miEnd = new MenuItem("Beenden", new MenuShortcut(KeyEvent.VK_B));
private MyActionListener myActionListener = new MyActionListener(this);

public Editor3()
{
super("Editor3");
this.menuDatei.add(miOpen);
this.menuDatei.add(miSave);
this.menuDatei.add(miClose);
this.menuDatei.add(miEnd);
this.menuBar.add(this.menuDatei);
this.setMenuBar(this.menuBar);
this.add(this.taText, BorderLayout.CENTER);
this.pack();
this.show();
this.addWindowListener(new MyWindowListener());
this.miOpen.addActionListener(myActionListener);
this.miSave.addActionListener(myActionListener);
this.miClose.addActionListener(myActionListener);
this.miEnd.addActionListener(myActionListener);
}

public static void main(String args[])
{
Editor3 f = new Editor3();
}
}
MyActionListener.java
import java.awt.event.*;
import java.awt.*;
import java.io.*;
public class MyActionListener implements ActionListener
{
public Editor3 f;
public MyActionListener(Editor3 f)
{
this.f=f;
}
public void actionPerformed(ActionEvent e)
{
if(e.getSource()==f.miOpen)
{
FileDialog fd = new FileDialog(f, "Öffnen...", FileDialog.LOAD);
fd.setFile("*.*");
fd.show();
String file = fd.getFile();
if(file!=null)
{
this.fileClose();
f.setTitle("Editor3 - "+file);
file=fd.getDirectory()+file;
BufferedReader in=null;
try
{
String zeile=null;
in = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
while((zeile=in.readLine())!=null)
f.taText.append(zeile+"\n");
in.close();
}
catch(FileNotFoundException err)
{
System.out.println("Datei-Fehler..."+err);
}
catch(IOException err)
{
System.out.println("Lesefehler..."+err);
}
}
}
if(e.getSource()==f.miSave)
{
FileDialog fd = new FileDialog(f, "Speichern...", FileDialog.SAVE);
fd.setFile("");
fd.show();
String file = fd.getFile();
if(file!=null)
{
f.setTitle("Editor3 - "+file);
file=fd.getDirectory()+file;
BufferedWriter out=null;
try
{
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file)));
out.write(f.taText.getText());
out.close();
}
catch(FileNotFoundException err)
{
System.out.println("Datei-Fehler..."+err);
}
catch(IOException err)
{
System.out.println("Schreibfehler..."+err);
}
}
}
if(e.getSource()==f.miClose)
{
f.setTitle("Editor3");
this.fileClose();
}
if(e.getSource()==f.miEnd) System.exit(0);
}
private void fileClose()
{
f.setTitle("Editor3");
f.taText.selectAll();
f.taText.replaceRange("",0,f.taText.getSelectionEnd());
}
}

Wir haben mit der fileClose-Methode Anweisungen ausgegliedert. So kann man die Methode fileClose() an zwei Stellen (open und close) einsetzen und spart sich so unter anderem die Anweisungen zweimal schreiben zu müssen.
So sieht unser Frame mit dem Menü aus:

Menü im Fenster

Swing
Wie ich eingangs erklärt habe, sind die Swing-Klassen die Weiterentwicklung des AWT. Sie sind ebenfalls zur grafischen Benutzeroberflächengestaltung entworfen, zeichnen jedoch jede Komponente durch Java-Code und greifen nicht wie das AWT auf Betriebssystemsfunktionen zurück. Somit sehen auch die durch Swing erstellten Komponenten überall gleich aus.
Ich möchte nur kurz auf die Unterschiede von Swing zum AWT eingehen.

JFrame und JDialog
JFrame und JDialog sind neben JWindow und JApplet die einzigen Klassen von Swing, die auf die klassischen AWT-Oberklassen zugreifen. JFrame (javax.swing.JFrame) hat die AWT-Oberklasse Frame (java.awt.Frame) und JDialog (javax.swing.JDialog) hat Dialog (java.awt.Dialog) als Oberklasse.
Somit wird klar, wie das Swing-Konzept entworfen wurde: Die Darstellung des Fensterrahmens (z.B. durch das JFrame/Frame-Objekt) bestimmt das Betriebssystem, das Innere des Fensters wird dagegen komplett von Java übernommen.

Aufbau der JRootPane
Soviel zu dem konzeptionellen Unterschied der beiden Techniken. Es gibt aber noch weitere Unterschiede und mit diesen wollen wir uns nun beschäftigen. Der innere Bereich des Fensters wird durch einen einzigen untergeordneten Container vom Typ JRootPane verwaltet, der wiederum aus zwei Komponenten besteht:

  • Das glassPane-Objekt sitzt als oberste Komponente über dem kompletten sichtbaren Bereich des inneren Fensters und ist normalerweise nicht sichtbar. Der Sinn dieser Komponente besteht darin, einmal sichtbar gemacht, alle Ereignisse im Fensterbereich abzufangen, um auf diese Weise z.B. länger andauernde Aktionen zu schützen (Blockieren von Maus/Tastatur)
  • Das layeredPane-Objekt verwaltet die untergeordneten Schichten des Fensters in mehreren Bereichen. Dabei werden die Komponenten einer höheren Schicht immer über die der darunter liegenden Schicht gezeichnet. Dadurch lassen sich u.a. Menüs konstruieren, deren Inhalt über den restlichen visuellen Dialogelementen gezeichnet werden muss.

Das layeredPane-Objekt enthält zwei untergeordnete Komponenten. Diese Komponenten sind die Menüleiste (vom Typ JMenuBar) sowie der darunter liegende Container contentPane, dem die visuellen Dialogkomponenten (z.B. Buttons) hinzugefügt werden.
Durch diesen Sachverhalt ergibt sich ein wesentlicher Unterschied beim Hinzufügen von Komponenten zu einem Swing-Fenster. Es reicht nicht mehr aus, die Komponenten einfach mittels add-Methode des JFrame-Objekts aufzurufen. Man muss die Komponenten dem contentPane-Objekt hinzufügen. Natürlich muss man dieses Objekt erst mit einer Methode (der getContentPane-Methode des Fensters) erzeugen.

JButton
Der JButton verhält sich genauso wie der aus dem AWT bekannte Button. Zusätzlich gibt es aber auch noch die Möglichkeit ein Icon auf dem Button zu platzieren. So sieht der Konstruktor aus: JButton(String str, javax.swing.Icon icon)
Man kann natürlich sowohl das Icon als auch den Text weglassen.
Beim folgenden Quelltext ist wieder die bekannte "Drei-Klassen-Gesellschaft" (Hauptklasse, MyActionListener, MyWindowListener) die wir bereits vom AWT kennen wieder zu finden. Hier ist die Hauptklasse:

import java.awt.*;
import javax.swing.*;
public class JFrame1 extends JFrame
{
private MyWindowListener myWindowListener = new MyWindowListener();
private MyActionListener myActionListener = new MyActionListener();
private JButton btnBeenden = new JButton("Beenden", new ImageIcon("Kreuz.gif"));

public JFrame1()
{
super("Unser erstes Swing-Fenster");
Container cp = this.getContentPane();
cp.setLayout(new FlowLayout());
this.setSize(400,100);
cp.add(this.btnBeenden);
this.show();
this.addWindowListener(myWindowListener);
this.btnBeenden.addActionListener(myActionListener);
}

public static void main(String argv[])
{
JFrame1 fenster = new JFrame1();
}
}

Hier sieht man die Unterschiede zum AWT-Konzept: Es wird ein Container-Objekt mit Verweis auf die contentPane-Ebene des Fensters angelegt. Das contentPane-Objekt ist direkt dafür verantwortlich, wie die Komponenten auf der Oberfläche platziert werden. Deswegen wird für das Container-Objekt der Layout-Manager definiert. Der JButton wird zur ContentPane-Ebene hinzugefügt.
Das Icon (in unserem Fall Kreuz.gif) muss im Verzeichnis liegen in dem sich auch die Quellcode-Dateien befinden.
Durch die Ähnlichkeit zum AWT-Design ändert sich am Aufbau der Listener nichts. Man kann die Listener im JCreator hinzufügen, indem man mittels Rechtsklick im FileView (links oben) auf den Projektnamen (z.B. JFrame1) das Kontextmenü öffnet und dort den Menüpunkt Add auswählt und dann zu Add Existing Files auswählt. Nun kann man die Dateien aus einem anderen Projekt hinzufügen (z.B. aus Fenster6). Es erscheint eine Abfrage ob man die Dateien adden will oder als externe Dateien im Projekt aufführen möchte. Wir wollen die Dateien adden. Schon sind die Dateien eingebunden.
Und so sieht das mit Swing designte Fenster aus:

Fenster mit Swing

Abschluss
Nun kennt man die grundlegenden Techniken um mit Java eine grafische Benutzeroberfläche zu erstellen. Damit kann man, zugegebenermaßen auf eine nicht so ganz einfache Art und Weise, professionelle Programme mit Java erstellen. Aber die beste Benutzeroberfläche ist nichts gegen eine gute Idee. Und um diese Idee zu verwirklichen gibt es noch einige weitere fortschrittliche Techniken, die man kennenlernen muss.

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)