From 33613a85afc4b1481367fbe92a17ee59c240250b Mon Sep 17 00:00:00 2001
From: Sven Eisenhauer
+In Swing können alle Hauptfenster mit Ausnahme von JWindow
+eine Menüleiste haben. Dabei handelt es sich um eine Instanz
+der Klasse JMenuBar,
+die dem Hauptfenster durch Aufruf von addJMenuBar
+hinzugefügt wird. JMenuBar
+besitzt eine Vielzahl von Methoden, meist werden aber lediglich der
+parameterlose Konstruktor und die Methode add
+benötigt.
+
+
+
+Swing-Menüs und ihre Bestandteile haben starke Ähnlichkeit
+mit den korrespondierenden Konzepten im AWT. Viele der in Kapitel 30
+erläuterten Eigenschaften gelten damit analog für Swing-Menüs.
+Die einzelnen Menüs einer Menüleiste sind Instanzen der
+Klasse JMenu,
+die aus JMenuItem
+abgeleitet ist. Ihre wichtigsten Methoden sind:
+
+
+Der Konstruktor erzeugt ein neues Menü mit dem angegebenen Namen.
+Mit add
+werden Menüeinträge hinzugefügt. Im allgemeinen Fall
+sind das Instanzen der Klasse JMenuItem,
+die auf vielfältige Weise konfiguriert werden können. Es
+ist aber auch möglich, lediglich Strings an add
+zu übergeben. Dadurch wird ein einfacher Menüeintrag dieses
+Namens angefügt. Mit addSeparator
+wird eine Trennlinie hinter dem letzten Menüpunkt angefügt.
+
+
+Für OO-Neulinge ist es schwer zu verstehen, warum ein Menü
+die Ableitung eines Menüeintrags ist. Eine einfache Erklärung
+ist, dass es möglich sein soll, Menüs ineinander zu schachteln.
+Daß also ein Element eines Menüs, das ja per Definition
+ein Menüeintrag ist, wahlweise auch ein Menü enthalten soll.
+Das kann nur erreicht werden, wenn Menü und Menüeintrag
+zuweisungskompatibel, also voneinander abgeleitet, sind. Eine ausführlichere
+Erklärung findet sich bei der Besprechung des Composite-Patterns
+in Abschnitt 10.4.7.
+Die Klasse JMenuItem
+repräsentiert Menüeinträge, also Elemente, die sich
+in einem Menü befinden. Dabei handelt es sich um Texte, die wahlweise
+mit einem Icon oder einem Häkchen versehen werden können.
+Da JMenu
+aus JMenuItem
+abgeleitet ist, kann ein Menü wiederum Menüs als Einträge
+enthalten. Auf diese Weise lassen sich Menüs schachteln. Die
+wichtigsten Eigenschaften von JMenuItem
+sind:
+
+
+Der an den Konstruktor übergebene String text
+legt den Menütext fest. Wahlweise kann zusätzlich ein Icon
+übergeben werden, das neben dem Menütext angezeigt wird.
+Mit setMnemonic
+wird das mnemonische Kürzel des Menüeintrags festgelegt.
+Das ist ein (unterstrichen dargestellter) Buchstabe innerhalb des
+Menütexts, der bei geöffnetem Menü gedrückt werden
+kann, um den Menüeintrag per Tastatur aufzurufen. Wahlweise kann
+das Kürzel auch schon an den Konstruktor übergeben werden.
+Mit getMnemonic
+kann es abgefragt werden.
+
+
+Neben den mnemonischen Kürzeln gibt es eine weitere Möglichkeit,
+Menüeinträge über Tastenkürzel aufzurufen. Diese
+als Acceleratoren oder Beschleunigertasten
+bezeichneten Tasten können auch dann verwendet werden, wenn das
+entsprechende Menü nicht geöffnet ist. Beschleuniger werden
+mit setAccelerator
+zugewiesen. Sie bestehen aus einer Kombination von normalen Tasten
+und Umschalttasten, die durch ein KeyStroke-Objekt
+beschrieben werden.
+
+
+Instanzen der Klasse KeyStroke
+werden ausschließlich mit ihrer Factory-Methode getKeyStroke
+erzeugt:
+
+
+In der einfachsten Form wird lediglich ein einzelnes Zeichen übergeben.
+In diesem Fall repräsentiert der erzeugte KeyStroke
+genau die entsprechende Taste. Soll diese zusammen mit Umschalttasten
+gedrückt werden, muss die gewünschte Kombination an den
+Parameter modifiers übergeben
+werden:
+
+
+
+Tabelle 36.2: Konstanten für Umschalttasten
+Diese Konstanten stammen aus der Klasse java.awt.Event.
+Sie werden durch unterschiedliche Zweierpotenzen repräsentiert
+und können durch Addition beliebig kombiniert werden. Als erstes
+Argument keyCode ist einer der
+in java.awt.event.KeyEvent
+definierten virtuellen Tastencodes zu übergeben (siehe Tabelle 29.4).
+
+
+Mit den Methoden setEnabled
+und getEnabled
+kann auf den Aktivierungszustand des Menüeintrags zugegriffen
+werden. Wird false
+an setEnabled
+übergeben, wird der Eintrag deaktiviert, andernfalls aktiviert.
+Ein deaktivierter Eintrag wird grau dargestellt und kann nicht ausgewählt
+werden.
+
+
+Die beiden letzten Methoden addActionListener
+und removeActionListener
+dienen dazu, Objekte als Listener zu registrieren (bzw. zu deregistrieren).
+Solche Objekte müssen das Interface ActionListener
+implementieren. Sie werden beim Auswählen des Menüpunkts
+aktiviert, indem ihre Methode actionPerformed
+aufgerufen wird. Details können in Abschnitt 30.5
+nachgelesen werden.
+
+
+Das folgende Programm zeigt eine Swing-Anwendung mit einem einfachen
+»Datei«-Menü, das die Einträge »Öffnen«,
+»Speichern« und »Beenden« besitzt. Das Menü
+und seine Einträge besitzen mnemonische Kürzel, und die
+Menüpunkte »Öffnen« und »Speichern«
+sind über die Beschleuniger [STRG]+[O]
+bzw. [STRG]+[S]
+zu erreichen. Das Applikationsobjekt registriert sich als ActionListener
+bei allen Menüpunkten und gibt die Benutzeraktionen auf der Console
+aus. Das Programm erzeugt zunächst eine neue Menüleiste
+und fügt ihr in Zeile 016
+das in createFileMenu erzeugte
+Menü hinzu. Schließlich wird die Menüleiste mit setJMenuBar
+an das Hauptfenster übergeben.
+
+
+
+
+
+
+ Titel
+ Inhalt
+ Suchen
+ Index
+ DOC
+ Handbuch der Java-Programmierung, 5. Auflage
+
+ <<
+ <
+ >
+ >>
+ API
+ Kapitel 36 - Swing: Container und Menüs
+
+
+
+
+
+36.2 Menüs
+
+
+
+
+
+
+
+
+36.2.1 Einfache Menüs
+
+
+
+
+36.2.2 Grundlagen von Swing-Menüs
+
+
+
+
+JMenuBar
+
+
+
+
+
+
+
+
+
+public JMenuBar()
+
+public JMenu add(JMenu c)
+
+
+
+javax.swing.JMenuBar
+
+
+
+
+
+
+
+
+
+
+![]()
+
+
+
+![]()
+
+
+
+
+
+ Hinweis
+
+
JMenu
+
+
+
+
+
+
+
+
+
+
+public JMenu(String s)
+
+public JMenuItem add(String s)
+public JMenuItem add(JMenuItem menuItem)
+
+public void addSeparator()
+
+
+
+javax.swing.JMenu
+
+
+
+
+
+
+
+
+
+
+![]()
+
+
+
+![]()
+
+
+
+
+
+ Hinweis
+
+
JMenuItem
+
+
+
+
+
+
+
+
+
+
+public JMenuItem(String text)
+public JMenuItem(String text, Icon icon)
+public JMenuItem(String text, int mnemonic)
+
+public void setMnemonic(char mnemonic)
+public void setMnemonic(int mnemonic)
+public int getMnemonic()
+
+public void setAccelerator(KeyStroke keyStroke)
+public KeyStroke getAccelerator()
+
+public void setEnabled(boolean b)
+public boolean isEnabled()
+
+public void addActionListener(ActionListener l)
+public void removeActionListener(ActionListener l)
+
+
+
+javax.swing.JMenuItem
+
+
+
+
+
+
+
+
+
+public static KeyStroke getKeyStroke(char keyChar)
+public static KeyStroke getKeyStroke(int keyCode, int modifiers)
+
+
+
+javax.swing.KeyStroke
+
+
+
+
+
+Konstante
+Bedeutung
+
+SHIFT_MASK
+[UMSCHALT]
+
+CTRL_MASK
+[STRG]
+
+META_MASK
+[META]
+(gibt es auf den meisten Plattformen nicht)
+
+ALT_MASK
+[ALT]
+
+
+Listing 36.8: Ein Swing-Programm mit einem einfachen Menü
+
+
+
+
+
+001 /* Listing3608.java */
+002
+003 import java.awt.*;
+004 import java.awt.event.*;
+005 import javax.swing.*;
+006
+007 public class Listing3608
+008 extends JFrame
+009 implements ActionListener
+010 {
+011 public Listing3608()
+012 {
+013 super("Swing-Menütest");
+014 addWindowListener(new WindowClosingAdapter(true));
+015 JMenuBar menubar = new JMenuBar();
+016 menubar.add(createFileMenu());
+017 setJMenuBar(menubar);
+018 }
+019
+020 public void actionPerformed(ActionEvent event)
+021 {
+022 System.out.println(event.getActionCommand());
+023 }
+024
+025 //---Private Methoden---------------
+026 private JMenu createFileMenu()
+027 {
+028 JMenu ret = new JMenu("Datei");
+029 ret.setMnemonic('D');
+030 JMenuItem mi;
+031 //Öffnen
+032 mi = new JMenuItem("Öffnen", 'f');
+033 setCtrlAccelerator(mi, 'O');
+034 mi.addActionListener(this);
+035 ret.add(mi);
+036 //Speichern
+037 mi = new JMenuItem("Speichern", 'p');
+038 setCtrlAccelerator(mi, 'S');
+039 mi.addActionListener(this);
+040 ret.add(mi);
+041 //Separator
+042 ret.addSeparator();
+043 //Beenden
+044 mi = new JMenuItem("Beenden", 'e');
+045 mi.addActionListener(this);
+046 ret.add(mi);
+047 return ret;
+048 }
+049
+050 private void setCtrlAccelerator(JMenuItem mi, char acc)
+051 {
+052 KeyStroke ks = KeyStroke.getKeyStroke(
+053 acc, Event.CTRL_MASK
+054 );
+055 mi.setAccelerator(ks);
+056 }
+057
+058 public static void main(String[] args)
+059 {
+060 Listing3608 frame = new Listing3608();
+061 frame.setLocation(100, 100);
+062 frame.setSize(300, 200);
+063 frame.setVisible(true);
+064 }
+065 }
+
+
+Listing3608.java
+
+Das Programm sieht mit geöffnetem "Datei"-Menü so aus: +
+ +
+Abbildung 36.9: Ein Swing-Programm mit einem einfachen Menü
+ + + + ++Das Einbinden von Untermenüs ist einfach. Da Menu +aus MenuItem +abgeleitet ist, kann an die Methode add +der Klasse Menu +auch eine Instanz der Klasse Menu +übergeben werden. Der Name des Untermenüs erscheint dann +an der Einfügestelle, und mit einem kleinen Pfeil wird angezeigt, +dass es sich um ein Untermenü handelt. + + + + +
+Einem Menüeintrag kann auch ein Icon zugeordnet werden. Dazu +kann ein Icon-Objekt +entweder direkt an den Konstruktor von MenuItem +übergeben werden, oder es kann später durch Aufruf von setIcon +zugewiesen werden. Icon +ist ein Interface, das die abstrakten Eigenschaften eines Icons definiert. +Es besitzt eine Implementierung ImageIcon, +mit der sehr einfach aus einer gif- oder +jpeg-Datei ein Icon +erzeugt werden kann: +
+
+
++public ImageIcon(String filename) ++ + |
++javax.swing.ImageIcon | +
+
![]() |
+![]() |
+
+
+ +Standardmäßig wird das Icon eines Menüeintrags links +von seiner Beschriftung platziert. Um es anders anzuordnen, kann auf +dem Menüeintrag die Methode setHorizontalTextPosition +aufgerufen und eine der Konstanten RIGHT, +LEFT, +CENTER, +LEADING +oder TRAILING +aus dem Interface SwingConstants +übergeben werden. |
+
+
|
+![]() |
+
+
![]() |
+
+
+ +SwingConstants +ist ein Interface im Paket javax.swing, +das eine Reihe von Konstanten definiert, mit denen die Position und +Orientierung von Swing-Komponenten beschrieben werden kann. Wir werden +die Konstanten näher beschreiben, wenn sie als Parameter einer +Methode auftauchen. Tabelle 36.3 +listet alle Elemente überblicksartig auf: + + +
+Tabelle 36.3: Die Konstanten der Klasse SwingConstants + |
+
+
|
+![]() |
+
+Auch Checkboxen und Radiobuttons können in Menüeinträgen +untergebracht werden. Das ist mit Hilfe der aus JMenuItem +abgeleiteten Klassen JCheckBoxMenuItem +und JRadioButtonMenuItem +ebenfalls recht einfach. + +
+JCheckBoxMenuItem +stellt ähnliche Konstruktoren wie JMenuItem +zur Verfügung und besitzt zusätzlich die Methoden getState +und setState, +mit denen auf seinen aktuellen Zustand zugegriffen werden kann. Wahlweise +kann bereits an den Konstruktor der Anfangszustand der Checkbox übergeben +werden: +
+
+
++public JCheckBoxMenuItem(String text) +public JCheckBoxMenuItem(String text, Icon icon) +public JCheckBoxMenuItem(String text, boolean b) +public JCheckBoxMenuItem(String text, Icon icon, boolean b) + +public boolean getState() +public void setState(boolean b) ++ + |
++javax.swing.JCheckBoxMenuItem | +
+Im Gegensatz zu einem JCheckBoxMenuItem +wird ein JRadioButtonMenuItem +immer dann verwendet, wenn von mehreren Buttons nur einer zur Zeit +aktiviert werden soll. Die wichtigsten Konstruktoren beider Klassen +sind identisch: +
+
+
++public JRadioButtonMenuItem(String text) +public JRadioButtonMenuItem(String text, Icon icon) +public JRadioButtonMenuItem(String text, boolean b) +public JRadioButtonMenuItem(String text, Icon icon, boolean b) ++ + |
++javax.swing.JRadioButtonMenuItem | +
+Die Kontrolle des Zustands der Buttons erfolgt mit einem ButtonGroup-Objekt. +Es wird vor dem Erzeugen der Menüeinträge angelegt, und +jeder JRadioButtonMenuItem +wird mit add +hinzugefügt: +
+
+
++public void add(AbstractButton b) ++ + |
++javax.swing.ButtonGroup | +
+Das ButtonGroup-Objekt +sorgt automatisch dafür, dass zu jedem Zeitpunkt genau ein Eintrag +selektiert ist. Auf den aktuellen Zustand jedes Menüeintrags +kann mit Hilfe der Methoden isSelected +und setSelected +zugegriffen werden: +
+
+
++public boolean isSelected() +public void setSelected(boolean b) ++ + |
++javax.swing.JRadioButtonMenuItem | +
+Das folgende Programm zeigt alle weiterführenden Möglichkeiten +im Überblick. Es definiert ein Menü »Extras«, +dessen oberster Eintrag »Tools« ein Untermenü mit sechs +weiteren Einträgen ist. Darunter befinden sich zwei Checkbox- +und drei RadioButton-Menüeinträge, die durch Anklicken aktiviert +werden können. Der letzte Menüeintrag »Sicherheit« +enthält zusätzlich ein Icon, das ein geöffnetes Vorhängeschloß +zeigt. + + +
+
+
+
+001 /* Listing3609.java */
+002
+003 import java.awt.*;
+004 import java.awt.event.*;
+005 import javax.swing.*;
+006
+007 public class Listing3609
+008 extends JFrame
+009 {
+010 public Listing3609()
+011 {
+012 super("Swing-Menütest II");
+013 addWindowListener(new WindowClosingAdapter(true));
+014 JMenuBar menubar = new JMenuBar();
+015 menubar.add(createExtrasMenu());
+016 setJMenuBar(menubar);
+017 }
+018
+019 //---Private Methoden---------------
+020 private JMenu createExtrasMenu()
+021 {
+022 JMenu ret = new JMenu("Extras");
+023 ret.setMnemonic('X');
+024 JMenuItem mi;
+025 //Tools-Untermenü
+026 ret.add(createToolsSubMenu());
+027 //Separator
+028 ret.addSeparator();
+029 //Statuszeile und Buttonleiste
+030 mi = new JCheckBoxMenuItem("Statuszeile");
+031 mi.setMnemonic('z');
+032 ((JCheckBoxMenuItem)mi).setState(true);
+033 ret.add(mi);
+034 mi = new JCheckBoxMenuItem("Buttonleiste");
+035 mi.setMnemonic('B');
+036 ret.add(mi);
+037 //Separator
+038 ret.addSeparator();
+039 //Offline, Verbinden, Anmelden
+040 ButtonGroup bg = new ButtonGroup();
+041 mi = new JRadioButtonMenuItem("Offline", true);
+042 mi.setMnemonic('O');
+043 ret.add(mi);
+044 bg.add(mi);
+045 mi = new JRadioButtonMenuItem("Verbinden");
+046 mi.setMnemonic('V');
+047 ret.add(mi);
+048 bg.add(mi);
+049 mi = new JRadioButtonMenuItem("Anmelden");
+050 mi.setMnemonic('A');
+051 ret.add(mi);
+052 bg.add(mi);
+053 //Separator
+054 ret.addSeparator();
+055 //Sicherheit
+056 mi = new JMenuItem(
+057 "Sicherheit",
+058 new ImageIcon("lock.gif")
+059 );
+060 mi.setMnemonic('S');
+061 mi.setHorizontalTextPosition(JMenuItem.LEFT);
+062 ret.add(mi);
+063 return ret;
+064 }
+065
+066 private JMenu createToolsSubMenu()
+067 {
+068 JMenu ret = new JMenu("Tools");
+069 ret.setMnemonic('T');
+070 ret.add(new JMenuItem("Rechner", 'R'));
+071 ret.add(new JMenuItem("Editor", 'E'));
+072 ret.add(new JMenuItem("Browser", 'B'));
+073 ret.add(new JMenuItem("Zipper", 'Z'));
+074 ret.add(new JMenuItem("Snapper", 'S'));
+075 ret.add(new JMenuItem("Viewer", 'V'));
+076 return ret;
+077 }
+078
+079 public static void main(String[] args)
+080 {
+081 Listing3609 frame = new Listing3609();
+082 frame.setLocation(100, 100);
+083 frame.setSize(300, 200);
+084 frame.setVisible(true);
+085 }
+086 }
+
+ |
++Listing3609.java | +
+Mit geöffneten Menüs stellt sich das Programm so dar: +
+ +
+Abbildung 36.10: Ein Swing-Programm mit einem umfangreichen Menü
++
![]() |
+![]() |
+
+
+ +Im JDK 1.3 arbeitet das Programm unter Windows fehlerhaft. Nach einmaligem +Anklicken des Menüeintrags »Sicherheit« kann das Untermenü +»Tools« nicht mehr per Maus aufgerufen werden, weil im Event-Thread +eine NullPointerException +ausgelöst wird. Die Tastaturbedienung ist dagegen weiterhin möglich. +Dieser seit dem RC2 des JDK 1.3 bekannte Fehler wurde leider bis zur +endgültigen Version des JDK 1.3 nicht mehr behoben. Seit dem +JDK 1.3.1 tritt er allerdings nicht mehr auf. |
+
+
|
+![]() |
+
+Kontextmenüs für AWT-Programme wurden bereits in Abschnitt 30.6 +ausführlich besprochen. In Swing-Programmen werden Kontextmenüs +mit Hilfe der Klasse JPopupMenu +erzeugt. Sie kann parameterlos instanziert werden und stellt Methoden +ähnlich JMenu +zur Verfügung: +
+
+
++public JMenuItem add(JMenuItem menuItem) +public JMenuItem add(String s) + +public void addSeparator() + +public void show(Component invoker, int x, int y) ++ + |
++javax.swing.JPopupMenu | +
+Mit add +werden Menüeinträge hinzugefügt, mit addSeparator +eine Trennlinie. Kontextmenüs können prinzipiell ebenso +komplex aufgebaut sein wie normale Menüs, also inbesondere Icons, +Untermenüs, Checkboxen oder Radiobuttons enthalten. Um das Menü +anzuzeigen, ist show +aufzurufen. Die dazu erforderlichen Koordinaten gewinnt man am besten +aus der aktuellen Position des Mauszeigers, die im Mausereignis mitgeliefert +wird. + +
+Die zum Aktivieren eines Kontextmenüs erforderliche Mausaktion +kann von Plattform zu Plattform unterschiedlich sein. Die portabelste +Lösung besteht darin, einen MouseListener +auf der Komponente zu registrieren, und bei jedem Mausereignis mit +isPopupTrigger +abzufragen, ob es sich um eine Aktion zum Aufrufen eines Kontextmenüs +handelte. + +
+Das folgende Programm zeigt ein Hauptfenster, auf dem ein Kontextmenü +mit den Einträgen »Rueckgaengig«, »Ausschneiden«, +»Kopieren« und »Einfuegen« aufgerufen werden kann. +Der Aufruf des Kontextmenüs erfolgt durch Abfrage der Mausereignisse. +Beim Auswählen einer Menüaktion wird der Kommandoname auf +der Konsole ausgegeben. + + +
+
+
+
+001 /* Listing3610.java */
+002
+003 import java.awt.*;
+004 import java.awt.event.*;
+005 import javax.swing.*;
+006 import javax.swing.border.*;
+007
+008 public class Listing3610
+009 extends JFrame
+010 implements MouseListener, ActionListener
+011 {
+012 public Listing3610()
+013 {
+014 super("Kontextmenüs");
+015 addWindowListener(new WindowClosingAdapter(true));
+016 addMouseListener(this);
+017 }
+018
+019 //MouseListener
+020 public void mouseClicked(MouseEvent event)
+021 {
+022 checkPopupMenu(event);
+023 }
+024
+025 public void mouseEntered(MouseEvent event)
+026 {
+027 }
+028
+029 public void mouseExited(MouseEvent event)
+030 {
+031 }
+032
+033 public void mousePressed(MouseEvent event)
+034 {
+035 checkPopupMenu(event);
+036 }
+037
+038 public void mouseReleased(MouseEvent event)
+039 {
+040 checkPopupMenu(event);
+041 }
+042
+043 private void checkPopupMenu(MouseEvent event)
+044 {
+045 if (event.isPopupTrigger()) {
+046 JPopupMenu popup = new JPopupMenu();
+047 //Rückgängig hinzufügen
+048 JMenuItem mi = new JMenuItem("Rueckgaengig");
+049 mi.addActionListener(this);
+050 popup.add(mi);
+051 //Separator hinzufügen
+052 popup.addSeparator();
+053 //Ausschneiden, Kopieren, Einfügen hinzufügen
+054 mi = new JMenuItem("Ausschneiden");
+055 mi.addActionListener(this);
+056 popup.add(mi);
+057 mi = new JMenuItem("Kopieren");
+058 mi.addActionListener(this);
+059 popup.add(mi);
+060 mi = new JMenuItem("Einfuegen");
+061 mi.addActionListener(this);
+062 popup.add(mi);
+063 //Menü anzeigen
+064 popup.show(
+065 event.getComponent(),
+066 event.getX(),
+067 event.getY()
+068 );
+069 }
+070 }
+071
+072 //ActionListener
+073 public void actionPerformed(ActionEvent event)
+074 {
+075 System.out.println(event.getActionCommand());
+076 }
+077
+078 public static void main(String[] args)
+079 {
+080 Listing3610 frame = new Listing3610();
+081 frame.setLocation(100, 100);
+082 frame.setSize(300, 200);
+083 frame.setVisible(true);
+084 }
+085 }
+
+ |
++Listing3610.java | +
| Titel + | Inhalt + | Suchen + | Index + | DOC + | Handbuch der Java-Programmierung, 5. Auflage, Addison +Wesley, Version 5.0.1 + |
| << + | < + | > + | >> + | API + | © 1998, 2007 Guido Krüger & Thomas +Stark, http://www.javabuch.de + |