Tit   Inh   Ind   1   2   3   4   5   6   7   8   9   10   11   12   13   14   15   16   17   18   19   20   21   22   23   24   25   26   27   28   29   30   31   32   <<   <   >   >> 

20.4 Menüeinträge



20.4.1 Einfache Menüeinträge

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

20.4.2 CheckboxMenuItem

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, daß 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, daß die neue Klasse Methoden zur Verfügung stellen kann, die zum Zugriff auf Menüs oder Menüeinträge verwendet werden können.

001 /* Listing2001.java */
002 
003 import java.awt.*;
004 import java.awt.event.*;
005 
006 class MainMenu1
007 extends MenuBar
008 {
009    private MenuItem miRueck;
010    private CheckboxMenuItem miFarbe;
011 
012    public MainMenu1()
013    {
014       Menu m;
015 
016       //Datei
017       m = new Menu("Datei");
018       m.add(new MenuItem("Neu"));
019       m.add(new MenuItem("Laden"));
020       m.add(new MenuItem("Speichern"));
021       m.addSeparator();
022       m.add(new MenuItem("Beenden"));
023       add(m);
024       //Bearbeiten
025       m = new Menu("Bearbeiten");
026       m.add((miRueck = new MenuItem("Rueckgaengig")));
027       m.addSeparator();
028       m.add(new MenuItem("Ausschneiden"));
029       m.add(new MenuItem("Kopieren"));
030       m.add(new MenuItem("Einfuegen"));
031       m.add(new MenuItem("Loeschen"));
032       add(m);
033       //Optionen
034       m = new Menu("Optionen");
035       m.add(new MenuItem("Einstellungen"));
036       m.add((miFarbe = new CheckboxMenuItem("Farbe")));
037       add(m);
038       //Rueckgaengig deaktivieren
039       enableRueckgaengig(false);
040       //Farbe anschalten
041       setFarbe(true);
042    }
043 
044    public void enableRueckgaengig(boolean ena)
045    {
046       if (ena) {
047          miRueck.setEnabled(true);
048       } else {
049          miRueck.setEnabled(false);
050       }
051    }
052 
053    public void setFarbe(boolean on)
054    {
055       miFarbe.setState(on);
056    }
057 }
058 
059 public class Listing2001
060 extends Frame
061 {
062    public static void main(String[] args)
063    {
064       Listing2001 wnd = new Listing2001();
065    }
066 
067    public Listing2001()
068    {
069       super("Listing2001");
070       setLocation(100,100);
071       setSize(400,300);
072       setMenuBar(new MainMenu1());
073       setVisible(true);
074       addWindowListener(
075          new WindowAdapter() {
076             public void windowClosing(WindowEvent event)
077             {
078                setVisible(false);
079                dispose();
080                System.exit(0);
081             }
082          }
083       );
084    }
085 }
Listing2001.java
Listing 20.1: Erzeugen von Menüs

 Beispiel 

Das Programm erzeugt eine Menüzeile mit den drei Einträgen »Datei«, »Bearbeiten« und »Optionen«, die in Abbildung 20.1 dargestellt werden:

Abbildung 20.1: Erzeugen von Menüs

20.4.3 Beschleunigertasten

In den meisten Programmen lassen sich Menüs nicht nur mit der Maus bedienen, sondern über Beschleunigertasten auch mit der Tastatur. Im JDK 1.0 konnten Beschleunigertasten unter Windows 95 ganz einfach dadurch eingefügt werden, daß an beliebiger Stelle im Menütext das Zeichen »&« eingefügt und so die nachfolgende Taste als Beschleuniger definiert wurde. Dies war natürlich nicht portabel, funktionierte nur unter Windows und wurde folglich als Bug angesehen und eliminiert.

 Warnung 

Das JDK 1.1 implementiert nun 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 muß, um den Menüeintrag aufzurufen.

Um einen Beschleuniger zu definieren, muß 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 19). 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, daß 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

Aufgrund eines Bugs im AWT (der auch im JDK 1.2 noch enthalten ist) muß nach der Definition eines Beschleunigers zusätzlich die Methode setActionCommand aufgerufen werden, um den String, der beim Auslösen des Beschleunigers an den ActionListener gesendet werden soll, festzulegen:

public void setActionCommand(String command)
java.awt.MenuItem

Ohne diesen Aufruf würde ein null-Objekt gesendet werden. 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.setActionCommand("Neu");
011 mi.addActionListener(listener);
012 m.add(mi);
Listing 20.2: Erzeugen eines Menüeintrags mit Beschleuniger

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       mi.setActionCommand("Neu");
018       m.add(mi);
019 
020       ms = new MenuShortcut(KeyEvent.VK_L);
021       mi = new MenuItem("Laden",ms);
022       mi.setActionCommand("Laden");
023       m.add(mi);
024 
025       ms = new MenuShortcut(KeyEvent.VK_S);
026       mi = new MenuItem("Speichern",ms);
027       mi.setActionCommand("Speichern");
028       m.add(mi);
029 
030       ms = new MenuShortcut(KeyEvent.VK_E);
031       mi = new MenuItem("Beenden",ms);
032       mi.setActionCommand("Beenden");
033       m.add(mi);
034       add(m);
035 
036       //Bearbeiten
037       m = new Menu("Bearbeiten");
038 
039       ms = new MenuShortcut(KeyEvent.VK_X);
040       mi = new MenuItem("Ausschneiden",ms);
041       mi.setActionCommand("Ausschneiden");
042       m.add(mi);
043 
044       ms = new MenuShortcut(KeyEvent.VK_C);
045       mi = new MenuItem("Kopieren",ms);
046       mi.setActionCommand("Kopieren");
047       m.add(mi);
048 
049       ms = new MenuShortcut(KeyEvent.VK_V);
050       mi = new MenuItem("Einfügen",ms);
051       mi.setActionCommand("Einfügen");
052       m.add(mi);
053       add(m);
054    }
055 }
MainMenu2.inc
Listing 20.3: Menüleisten mit zwei Menüs und Beschleunigertasten

 Beispiel 

Wir werden später weiter unten eine Methode vorstellen, die den Aufwand für das Erzeugen und Einfügen von Beschleunigern vermindert.

Die im JDK 1.1 eingeführten Beschleuniger haben Vor- und Nachteile. Ihr Vorteil ist, daß sie einfach zu erzeugen sind und über Plattformgrenzen hinweg funktionieren. Der Nachteil ist allerdings ihre eingeschränkte Funktionalität und die Unterschiede im Look & 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. Es bleibt zu hoffen, daß die nächste Version des AWT hier Verbesserungen bringt und eine umfassendere Menge der plattformspezifischen Features portabel zur Verfügung stellt.

20.4.4 Untermenüs

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 034):

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
Listing 20.4: Geschachtelte Menüs

Ein Aufruf des Untermenüs wird folgendermaßen dargestellt:

Abbildung 20.2: Geschachtelte Menüs


 Tit   Inh   Ind   1   2   3   4   5   6   7   8   9   10   11   12   13   14   15   16   17   18   19   20   21   22   23   24   25   26   27   28   29   30   31   32   <<   <   >   >> 
Go To Java 2, Addison Wesley, Version 1.0.2, © 1999 Guido Krüger, http://www.gkrueger.com