Menyer och verktygsfält

Följande exempel illustrerar mycket av menyhanteringen i Swing, Menus.java. Du kan hämta bilden genom att hålla nere shifttangenten och klicka här, plant.gif. Vi går igenom exemplet bit för bit.

JMenuItem

Ett menyelement är ett objekt av klassen JMenuItem. Den ärver av AbstractButton, vilket innebär dels att den har JComponents och AbstractButtons hela funktionalitet, dels att vilken subklass som helst till JComponent kan användas som menyelement. 

Ett menyelement kan ha en mnenomic, vilken kan anges antingen direkt i konstruktorn eller med metoden setMnemonic(). I exemplet ovan sätts den i konstruktorn. Raden item = new JMenuItem( "Paste", 'P' ) tilldelar mnemonic P till menyvalet paste på editmenyn. Det innebär att tangentkombinationen ALT-P genererar ett tryck på paste då editmenyn är uppe. Observera att den bokstav som anges måste finnas i menyelementets label och att den inte får vara mnemonic för menyns label.

Det går också att ange en genväg, i exemplet görs det med bland annat raden item.setAccelerator( KeyStroke.getKeyStroke( 'V', java.awt.Event.CTRL_MASK, false ) ). Detta gör att tangentkombinationen CTRL-V genererar ett tryck på item oavsett om dess meny är uppe eller inte. KeyStroke är en klass som används för att representera en tangentkombination.

Man kan placera en ikon bredvid texten. I exemplet ovan har ikonen angetts i konstruktorn med raden otherMenu.add( item = new JMenuItem( "Potted Plant", new ImageIcon( "plant.gif" ) ) ).

Checkbox och radiobutton

En checkbox eller radiobutton placeras i exemplet ut med raderna otherMenu.add( item = new JCheckBoxMenuItem( "Check Me" ) ) respektive
ButtonGroup buttonGroup = new ButtonGroup();
otherMenu.add(item = new JRadioButtonMenuItem("Radio 1"));
buttonGroup.add(item);
Precis som när det gäller knappar används en ButtonGroup för att max en radiobutton åt gången ska kunna vara vald.

JMenu

En meny representeras av klassen JMenu. Eftersom den ärver av JMenuItem går det bra att placera en meny inuti en annan meny. Det görs, precis på samma sätt som ett menyelement läggs till, men metoden add(). Se till exempel raden otherMenu.add( subMenu ) i exemplet. Även en meny kan ha en mnemonic. Det finns dock ingen konstruktor som tar den utan metoden setMnemonic() måste användas, som på raden editMenu.setMnemonic( 'E' ).

JMenuBar

Menyerna måste placeras i ett objekt av klassen JMenuBar, med hjälp av dess metod add(). Menyraden placeras sedan i till exempel en frame med metoden setJMenuBar(). Egentligen placeras menyraden i framens layeredPane, men det sköter Swing åt oss. SetJMenuBar() placerar menyraden där den normalt hör hemma, överst i framen. Men då JMenuBar ärver av JComponent går det lika bra att placera ut den var som helst med metoden add(), precis som vilken annan komponent som helst.

Separator

Ett objekt av JSeparator representerar en linje. I vårt menyexempel läggs ett sådant in till exempel med raden otherMenu.addSeparator(). Eftersom JSeparator ärver av JComponent går det att använda den även i exempelvis en frame, som vilken komponent som helst.

Popupmenyer

En popupmeny är en meny som inte finns på menyraden utan kan dyka upp var som helst på en komponents yta. Ett typiskt exempel är den meny som dyker upp när du högerklickar på något fönster. Här är ett exempel på en frame som visar en popupmeny när du högerklickar på den, PopupMenuExample.java. Håll ner shifttangenten och klicka här för att hämta bilderna left.gif, right.gif, center.gif, full.gif. Menyn dyker upp när höger musknapp släpps på framens yta, vilket är den metod som används i till exempel MS Office. MouseEvent har en metod, isPopupTrigger(), som returnerar true om aktuell mushändelse ska visa popupmenyer på aktuell plattform. På Windows är det höger musknapp som visar popupmenyer. Normalt behöver vi inte bry oss om att ta bort menyn, det sköts av Swing.

Lyssnarstrategier och händelser

Hur ska man veta när användaren gjort ett menyval? JMenuItem ärver hanteringen av ActionEvent från AbstractButton, dvs den skickar ett ActionEvent när användaren släpper musen på det alternativet. Det ActionEvent som skickas kommer att ha ActionCommand satt till menyelementets label. Förutom denna metod går det även bra att använda en Action. Dessutom skickar både JCeckBoxMenuItem och JRadioButtonMenuItem ett ItemEvent när deras tillstånd ändras.

Förutom vad som nämnts ovan skickar de olika menyklasserna en drös med händelser. Till exempel skickar JMenuItem MenuDragMouseEvent vid olika tillfällen när användaren drar musen över en meny och MenuKeyEvent när menyelementet tar emot en tangenttryckning, dvs har fokus och användaren trycker på en tangent. En JPopupMenu skickar ett PupupMenuEvent när den dyker upp eller försvinner från skärmen. En JMenu skickar ett MenuEvent för att tala om bland annat huruvida menyn är utfälld eller ej.

Verktygsfält

Ett verktygsfält representeras av klassen JToolBar, vilken ärver av JComponent. Du placerar ut den som alla andra komponenter, med metoden add(). Verktygsfältet kan innehålla vilka andra komponenter som helst. Default har det layouthanteraren BoxLayout, men det går att ändra.

Ett verktygsfält har en property floatable som default är sann. Är den sann går det att klicka på en tom yta på verktygsfältet och dra iväg det. Det placeras då i ett eget fönster. Om floatable är sann är det klokt att låta framen som innehåller verktygsfältet ha BorderLayout. Det går då att släppa verktygsfältet i någon av framens kanter och det kommer att fastna där.

Ett verktygsfält har även det en metod addSeparator(). Den har dock inget med klassen JSeparator att göra, utan infogar en tom yta i verktygsfältet.

Här är ett exempel som implementerar funktionaliteten ovan, ToolBarTest.java.