Titel | Inhalt | Suchen | Index | DOC | Handbuch der Java-Programmierung, 7. Auflage |
<< | < | > | >> | API | Kapitel 30 - Menüs |
Die Menüeinträge sind die elementaren Bestandteile eines Menüs. Sie besitzen einen Text, mit dem sie dem Anwender die dahinterstehende Funktion anzeigen. Wenn der zugehörige Menüpunkt aufgerufen wird, sendet das Programm eine Nachricht an das zugehörige Fenster, die dann zum Aufruf der entsprechenden Methode führt.
Menüeinträge werden in Java mit der Klasse MenuItem erzeugt. Ihr Konstruktor erwartet als Parameter einen String, der den Namen des Menüeintrags angibt:
public MenuItem(String label) |
java.awt.MenuItem |
Auch nach der Konstruktion eines Menüeintrags ist ein Zugriff auf seinen Namen möglich. Mit der Methode getLabel kann der Name des Menüeintrags abgefragt und mit setLabel sogar verändert werden:
public String getLabel() public void setLabel(String label) |
java.awt.MenuItem |
Neben einem Namen besitzt ein Menüeintrag eine interne Zustandsvariable, die anzeigt, ob er aktiv ist oder nicht. Nur ein aktiver Eintrag kann vom Anwender ausgewählt werden und so eine Nachricht auslösen. Ein inaktiver Eintrag dagegen wird im Menü grau dargestellt, kann vom Anwender nicht mehr ausgewählt werden und daher auch keine Nachricht mehr auslösen.
Nach dem Aufruf des Konstruktors ist ein Menüeintrag zunächst aktiviert. Er kann durch Aufruf von setEnabled(false) deaktiviert und mit setEnabled(true) aktiviert werden. Durch Aufruf von isEnabled kann der aktuelle Zustand abgefragt werden:
public void setEnabled(boolean b) public boolean isEnabled() |
java.awt.MenuItem |
Neben der Klasse MenuItem gibt es mit der Klasse CheckboxMenuItem eine zweite Klasse zum Erzeugen von Menüeinträgen. CheckboxMenuItem ist aus MenuItem abgeleitet und bietet als zusätzliches Feature eine interne Zustandsvariable, die zwischen true und false umgeschaltet werden kann. Die visuelle Darstellung der Zustandsvariablen erfolgt durch Anfügen oder Entfernen eines Häkchens neben dem Menüeintrag. Der Nutzen der Klasse CheckboxMenuItem besteht darin, dass eine logische Programmvariable durch Auswählen des Menüpunkts abwechselnd an- und ausgeschaltet werden kann.
Die Instanzierung eines CheckboxMenuItem erfolgt wie bei einem MenuItem. Zusätzlich stehen die beiden Methoden setState und getState zum Setzen und Abfragen des Zustands zur Verfügung:
public void setState(boolean state) public boolean getState() |
java.awt.CheckboxMenuItem |
Das folgende Programm stellt alle bisher erwähnten Eigenschaften in einem Beispiel dar. Es leitet dazu die Klasse MainMenu1 aus MenuBar ab und erzeugt im Konstruktor die Menüs und Menüeinträge. Gegenüber der einfachen Instanzierung von MenuBar bietet die Ableitung den Vorteil, dass die neue Klasse Methoden zur Verfügung stellen kann, die zum Zugriff auf Menüs oder Menüeinträge verwendet werden können.
001 /* Listing3001.java */ 002 003 import java.awt.*; 004 005 class MainMenu1 006 extends MenuBar 007 { 008 private MenuItem miRueck; 009 private CheckboxMenuItem miFarbe; 010 011 public MainMenu1() 012 { 013 Menu m; 014 015 //Datei 016 m = new Menu("Datei"); 017 m.add(new MenuItem("Neu")); 018 m.add(new MenuItem("Laden")); 019 m.add(new MenuItem("Speichern")); 020 m.addSeparator(); 021 m.add(new MenuItem("Beenden")); 022 add(m); 023 //Bearbeiten 024 m = new Menu("Bearbeiten"); 025 m.add((miRueck = new MenuItem("Rueckgaengig"))); 026 m.addSeparator(); 027 m.add(new MenuItem("Ausschneiden")); 028 m.add(new MenuItem("Kopieren")); 029 m.add(new MenuItem("Einfuegen")); 030 m.add(new MenuItem("Loeschen")); 031 add(m); 032 //Optionen 033 m = new Menu("Optionen"); 034 m.add(new MenuItem("Einstellungen")); 035 m.add((miFarbe = new CheckboxMenuItem("Farbe"))); 036 add(m); 037 //Rueckgaengig deaktivieren 038 enableRueckgaengig(false); 039 //Farbe anschalten 040 setFarbe(true); 041 } 042 043 public void enableRueckgaengig(boolean ena) 044 { 045 if (ena) { 046 miRueck.setEnabled(true); 047 } else { 048 miRueck.setEnabled(false); 049 } 050 } 051 052 public void setFarbe(boolean on) 053 { 054 miFarbe.setState(on); 055 } 056 } 057 058 public class Listing3001 059 extends Frame 060 { 061 public static void main(String[] args) 062 { 063 Listing3001 wnd = new Listing3001(); 064 } 065 066 public Listing3001() 067 { 068 super("Menüs"); 069 setLocation(100,100); 070 setSize(400,300); 071 setMenuBar(new MainMenu1()); 072 setVisible(true); 073 addWindowListener(new WindowClosingAdapter(true)); 074 } 075 } |
Listing3001.java |
Das Programm erzeugt eine Menüzeile mit den drei Einträgen »Datei«, »Bearbeiten« und »Optionen«, die in Abbildung 30.1 dargestellt wird:
Abbildung 30.1: Erzeugen von Menüs
In den meisten Programmen lassen sich Menüs nicht nur mit der Maus bedienen, sondern über Beschleunigertasten auch mit der Tastatur.
Das JDK implementiert ein eigenes Beschleunigerkonzept, das über Plattformgrenzen hinweg funktioniert. Dazu wurde die Klasse MenuShortcut eingeführt, mit deren Hilfe Beschleunigertasten definiert und an einzelne Menüeinträge angehängt werden können. Eine Beschleunigertaste ist dabei immer ein einzelnes Zeichen der Tastatur, das zusammen mit der systemspezifischen Umschalttaste für Beschleuniger ([STRG] unter Windows und Motif, [COMMAND] unter MAC-OS) gedrückt werden muss, um den Menüeintrag aufzurufen.
Um einen Beschleuniger zu definieren, muss zunächst eine Instanz der Klasse MenuShortcut erzeugt werden:
public MenuShortcut(int key) public MenuShortcut(int key, boolean useShiftModifier) |
java.awt.MenuShortcut |
Der erste Konstruktor erwartet den virtuellen Tastencode der gewünschten Beschleunigertaste (siehe Kapitel 29). Für einfache alphanumerische Zeichen kann hier auch das Zeichen selbst übergeben werden. Die Übergabe einer Funktionstaste ist leider nicht ohne Weiteres möglich, denn deren virtuelle Tastencodes überschneiden sich mit den ASCII-Codes der Kleinbuchstaben. Funktionstasten können daher nur dann als Beschleuniger verwendet werden, wenn ihre virtuellen Tastencodes die Umwandlung in Großbuchstaben unverändert überstehen (z.B. VK_DELETE). Der zweite Konstruktor erlaubt zusätzlich die Übergabe eines booleschen Parameters useShiftModifier, der dafür sorgt, dass der Beschleuniger nur dann greift, wenn neben der systemspezifischen Umschalttaste für Beschleuniger zusätzlich die Taste [UMSCHALT] gedrückt wird.
Um einen Beschleuniger an einen Menüpunkt zu binden, ist das MenuShortcut-Objekt als zweites Argument an den Konstruktor von MenuItem zu übergeben:
public MenuItem(String label, MenuShortcut s) |
java.awt.MenuItem |
Alternativ kann auch die Methode setShortCut aufgerufen werden:
public void setShortcut(MenuShortcut s) |
java.awt.MenuItem |
Durch Aufruf von deleteShortCut kann der einem Menüeintrag zugeordnete Beschleuniger gelöscht werden:
public void deleteShortcut() |
java.awt.MenuItem |
Eine beispielhafte Aufrufsequenz zur Erzeugung eines Menüeintrags mit Beschleuniger sieht damit so aus:
001 Menu m; 002 MenuItem mi; 003 MenuShortcut ms; 004 005 //Datei 006 m = new Menu("Datei"); 007 008 ms = new MenuShortcut(KeyEvent.VK_N); 009 mi = new MenuItem("Neu",ms); 010 mi.addActionListener(listener); 011 m.add(mi); |
Hier wird der Menüeintrag »Neu« wie im vorigen Beispiel generiert und mit der Beschleunigertaste [STRG]+[N] ausgestattet.
Das folgende Beispiel zeigt eine Menüleiste mit zwei Menüs »Datei« und »Bearbeiten«, bei denen alle Menüeinträge mit Beschleunigern ausgestattet wurden:
001 /* MainMenu2.inc */ 002 003 class MainMenu2 004 extends MenuBar 005 { 006 public MainMenu2() 007 { 008 Menu m; 009 MenuItem mi; 010 MenuShortcut ms; 011 012 //Datei 013 m = new Menu("Datei"); 014 015 ms = new MenuShortcut(KeyEvent.VK_N); 016 mi = new MenuItem("Neu",ms); 017 m.add(mi); 018 019 ms = new MenuShortcut(KeyEvent.VK_L); 020 mi = new MenuItem("Laden",ms); 021 m.add(mi); 022 023 ms = new MenuShortcut(KeyEvent.VK_S); 024 mi = new MenuItem("Speichern",ms); 025 m.add(mi); 026 027 ms = new MenuShortcut(KeyEvent.VK_E); 028 mi = new MenuItem("Beenden",ms); 029 m.add(mi); 030 add(m); 031 032 //Bearbeiten 033 m = new Menu("Bearbeiten"); 034 035 ms = new MenuShortcut(KeyEvent.VK_X); 036 mi = new MenuItem("Ausschneiden",ms); 037 m.add(mi); 038 039 ms = new MenuShortcut(KeyEvent.VK_C); 040 mi = new MenuItem("Kopieren",ms); 041 m.add(mi); 042 043 ms = new MenuShortcut(KeyEvent.VK_V); 044 mi = new MenuItem("Einfügen",ms); 045 m.add(mi); 046 add(m); 047 } 048 } |
MainMenu2.inc |
Wir werden später eine Methode vorstellen, die den Aufwand für das Erzeugen und Einfügen von Beschleunigern vermindert.
Die im JDK eingeführten Beschleuniger haben Vor- und Nachteile. Ihr Vorteil ist, dass sie einfach zu erzeugen sind und über Plattformgrenzen hinweg funktionieren. Die Nachteile sind allerdings ihre eingeschränkte Funktionalität und die Unterschiede im Look-and-Feel gegenüber den speziellen Beschleunigern des jeweiligen Betriebssystems. So gibt es unter Windows beispielsweise keine Beschleuniger mehr in der Menüleiste ([ALT]+Buchstabe) und auch Menüeinträge können nicht mehr mit [ALT]+Tastenkürzel aufgerufen werden (sie zeigen auch keinen unterstrichenen Buchstaben mehr an).
Außerdem wird eine Beschleunigertaste zwangsweise an die systemspezifische Umschalttaste gebunden. Es ist damit nicht möglich, einfache Tasten wie [EINFG] oder [ENTF] als Beschleuniger zu definieren. Des Weiteren lassen sich wegen der unglücklichen Umwandlung des virtuellen Tastencodes in Großbuchstaben viele Funktionstasten nicht als Beschleuniger verwenden. Dies sind sicherlich gravierende Restriktionen, die die Bedienung nicht unerheblich einschränken. Abschnitt 37.2 zeigt, dass es in der Swing-Grafikbibliothek erheblich bessere Möglichkeiten gibt.
Menüs lassen sich auf einfache Art und Weise schachteln. Dazu ist beim Aufruf der add-Methode anstelle einer Instanz der Klasse MenuItem ein Objekt der Klasse Menu zu übergeben, das das gewünschte Untermenü repräsentiert. Das folgende Beispiel erweitert das Menü »Optionen« der Klasse MainMenu1 um den Menüeintrag »Schriftart«, der auf ein Untermenü mit den verfügbaren Schriftarten verzweigt (der Code zur Erzeugung des Untermenüs steht in den Zeilen 034 bis 041):
001 /* MainMenu3.inc */ 002 003 class MainMenu3 004 extends MenuBar 005 { 006 private MenuItem miRueck; 007 private CheckboxMenuItem miFarbe; 008 009 public MainMenu3() 010 { 011 Menu m; 012 013 //Datei 014 m = new Menu("Datei"); 015 m.add(new MenuItem("Neu")); 016 m.add(new MenuItem("Laden")); 017 m.add(new MenuItem("Speichern")); 018 m.addSeparator(); 019 m.add(new MenuItem("Beenden")); 020 add(m); 021 //Bearbeiten 022 m = new Menu("Bearbeiten"); 023 m.add((miRueck = new MenuItem("Rueckgaengig"))); 024 m.addSeparator(); 025 m.add(new MenuItem("Ausschneiden")); 026 m.add(new MenuItem("Kopieren")); 027 m.add(new MenuItem("Einfuegen")); 028 m.add(new MenuItem("Loeschen")); 029 add(m); 030 //Optionen 031 m = new Menu("Optionen"); 032 m.add(new MenuItem("Einstellungen")); 033 034 //Untermenü Schriftart 035 Menu m1 = new Menu("Schriftart"); 036 m1.add(new MenuItem("Arial")); 037 m1.add(new MenuItem("TimesRoman")); 038 m1.add(new MenuItem("Courier")); 039 m1.add(new MenuItem("System")); 040 m.add(m1); 041 //Ende Untermenü Schriftart 042 043 m.add((miFarbe = new CheckboxMenuItem("Farbe"))); 044 add(m); 045 //Rueckgaengig deaktivieren 046 enableRueckgaengig(false); 047 //Farbe anschalten 048 setFarbe(true); 049 } 050 051 public void enableRueckgaengig(boolean ena) 052 { 053 if (ena) { 054 miRueck.setEnabled(true); 055 } else { 056 miRueck.setEnabled(false); 057 } 058 } 059 060 public void setFarbe(boolean on) 061 { 062 miFarbe.setState(on); 063 } 064 } |
MainMenu3.inc |
Ein Aufruf des Untermenüs wird folgendermaßen dargestellt:
Abbildung 30.2: Geschachtelte Menüs
Titel | Inhalt | Suchen | Index | DOC | Handbuch der Java-Programmierung, 7. Auflage, Addison Wesley, Version 7.0 |
<< | < | > | >> | API | © 1998, 2011 Guido Krüger & Heiko Hansen, http://www.javabuch.de |