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:
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:
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:
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.
|