構建一個功能完整的 Swing 選單系統:頂層 JMenuBar 包含多層次選單、圖示項目、單選按鈕組、核取方塊項目、子選單與快捷鍵;文字區右鍵彈出 JPopupMenu 提供情境操作。完整展示選單模型構建、事件監聽(ActionListener/ItemListener)、鍵盤助記符與加速鍵、彈出選單觸發機制。
public class MenuDemo implements ActionListener, ItemListener {
JTextArea output; JScrollPane scrollPane; String newline = "\n";
// 主選單列構建
public JMenuBar createMenuBar() {
JMenuBar menuBar = new JMenuBar();
// 選單 1
JMenu menu = new JMenu("(A)選單");
menu.setMnemonic(KeyEvent.VK_A);
// 純文字項目 + 快捷鍵 Alt+1
JMenuItem item = new JMenuItem("(O)純文字項目", KeyEvent.VK_O);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_1, ActionEvent.ALT_MASK));
item.addActionListener(this); menu.add(item);
// 圖示+文字項目
ImageIcon icon = createImageIcon("images/middle.gif");
item = new JMenuItem("(B)圖示+文字", icon);
item.setMnemonic(KeyEvent.VK_B); item.addActionListener(this); menu.add(item);
// 純圖示項目
item = new JMenuItem(icon); item.setMnemonic(KeyEvent.VK_D); item.addActionListener(this); menu.add(item);
menu.addSeparator();
// 單選按鈕組
ButtonGroup group = new ButtonGroup();
JRadioButtonMenuItem rb = new JRadioButtonMenuItem("(R)單選項目 1");
rb.setSelected(true); rb.setMnemonic(KeyEvent.VK_R); group.add(rb); rb.addActionListener(this); menu.add(rb);
rb = new JRadioButtonMenuItem("(D)單選項目 2");
rb.setMnemonic(KeyEvent.VK_D); group.add(rb); rb.addActionListener(this); menu.add(rb);
menu.addSeparator();
// 核取方塊項目
JCheckBoxMenuItem cb = new JCheckBoxMenuItem("(C)核取項目 1");
cb.setMnemonic(KeyEvent.VK_C); cb.addItemListener(this); menu.add(cb);
cb = new JCheckBoxMenuItem("(H)核取項目 2");
cb.setMnemonic(KeyEvent.VK_H); cb.addItemListener(this); menu.add(cb);
menu.addSeparator();
// 子選單
JMenu submenu = new JMenu("(S)子選單");
submenu.setMnemonic(KeyEvent.VK_S);
item = new JMenuItem("子選單項目 1");
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_2, ActionEvent.ALT_MASK));
item.addActionListener(this); submenu.add(item);
item = new JMenuItem("子選單項目 2"); item.addActionListener(this); submenu.add(item);
menu.add(submenu);
menuBar.add(menu);
// 選單 2
menu = new JMenu("(N)第二個選單");
menu.setMnemonic(KeyEvent.VK_N);
menuBar.add(menu);
return menuBar;
}
// 內容面板
public Container createContentPane() {
JPanel panel = new JPanel(new BorderLayout());
output = new JTextArea(5, 30); output.setEditable(false);
scrollPane = new JScrollPane(output);
panel.add(scrollPane, BorderLayout.CENTER);
return panel;
}
// 彈出選單
public void createPopupMenu() {
JPopupMenu popup = new JPopupMenu();
JMenuItem item = new JMenuItem("開啟檔案", createImageIcon("images/Open16.gif"));
item.addActionListener(this); popup.add(item);
item = new JMenuItem("儲存檔案", createImageIcon("images/Save16.gif"));
item.addActionListener(this); popup.add(item);
// 滑鼠監聽觸發彈出
output.addMouseListener(new PopupListener(popup));
}
// 事件處理
public void actionPerformed(ActionEvent e) {
JMenuItem src = (JMenuItem)e.getSource();
output.append("動作事件: " + src.getText() + " (" + getClassName(src) + ")" + newline);
}
public void itemStateChanged(ItemEvent e) {
JMenuItem src = (JMenuItem)e.getSource();
output.append("狀態改變: " + src.getText() + " -> " +
(e.getStateChange() == ItemEvent.SELECTED ? "選取" : "取消") + newline);
}
protected String getClassName(Object o) {
String cn = o.getClass().getName(); return cn.substring(cn.lastIndexOf('.')+1);
}
protected static ImageIcon createImageIcon(String path) {
java.net.URL url = MenuDemo.class.getResource(path);
return url != null ? new ImageIcon(url) : null;
}
// 彈出選單滑鼠觸發器
class PopupListener extends MouseAdapter {
JPopupMenu popup;
PopupListener(JPopupMenu p) { popup = p; }
public void mousePressed(MouseEvent e) { maybeShow(e); }
public void mouseReleased(MouseEvent e) { maybeShow(e); }
private void maybeShow(MouseEvent e) {
if (e.isPopupTrigger()) popup.show(e.getComponent(), e.getX(), e.getY());
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame("Menu Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
MenuDemo demo = new MenuDemo();
frame.setJMenuBar(demo.createMenuBar());
frame.setContentPane(demo.createContentPane());
demo.createPopupMenu();
frame.setSize(450, 260);
frame.setVisible(true);
});
}
}
| 類別 | 用途 | 事件監聽 | 視覺特徵 |
|---|---|---|---|
JMenuItem | 一般指令項目 | ActionListener | 文字/圖示/文字+圖示 |
JRadioButtonMenuItem | 互斥單選組 | ActionListener | 圓形單選按鈕,配合 ButtonGroup |
JCheckBoxMenuItem | 獨立開關狀態 | ItemListener | 方形核取方塊 |
JMenu | 子選單容器 | — | 展開顯示子項目 |
JPopupMenu | 情境彈出選單 | ActionListener | 滑鼠右鍵觸發 |
setMnemonic(KeyEvent.VK_X) → Alt+X 聚焦選單/項目(底線標示)。setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, ActionEvent.CTRL_MASK)) → Ctrl+S 直接觸發動作(無需開啟選單)。Enter 確認、Esc 關閉。mousePressed 和 mouseReleased,跨平台相容(Windows 釋放觸發,macOS 按下觸發)。e.isPopupTrigger() 判斷而非檢查按鈕編號。popup.show(component, x, y) 相對元件座標定位。item.setEnabled(false)。item.setIcon(selectedIcon)。Help → Keyboard Shortcuts 動態生成顯示所有加速鍵。