Java 菜单
在图形用户界面(GUI)应用程序中,菜单是一种常见且重要的用户交互元素,它允许用户通过选择菜单项来执行特定操作。Java提供了一套完整的菜单系统,使开发者可以轻松地为应用程序添加各种类型的菜单。
菜单系统概述
Java Swing库中的菜单系统主要包括以下组件:
- JMenuBar:菜单栏,通常位于窗口顶部,可包含多个JMenu
- JMenu:下拉菜单,包含多个菜单项
- JMenuItem:菜单项,用户可以点击执行相关操作
- JCheckBoxMenuItem:带有复选框的菜单项
- JRadioButtonMenuItem:带有单选按钮的菜单项
- JPopupMenu:弹出菜单,通常通过鼠标右键激活
创建基本菜单栏
让我们从创建一个简单的菜单栏开始:
java
import javax.swing.*;
import java.awt.event.*;
public class SimpleMenuExample extends JFrame {
public SimpleMenuExample() {
setTitle("菜单示例");
setSize(400, 300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 创建菜单栏
JMenuBar menuBar = new JMenuBar();
// 创建文件菜单
JMenu fileMenu = new JMenu("文件");
// 创建菜单项
JMenuItem newItem = new JMenuItem("新建");
JMenuItem openItem = new JMenuItem("打开");
JMenuItem saveItem = new JMenuItem("保存");
JMenuItem exitItem = new JMenuItem("退出");
// 添加菜单项到菜单
fileMenu.add(newItem);
fileMenu.add(openItem);
fileMenu.add(saveItem);
fileMenu.addSeparator(); // 添加分隔线
fileMenu.add(exitItem);
// 创建编辑菜单
JMenu editMenu = new JMenu("编辑");
// 创建菜单项
JMenuItem cutItem = new JMenuItem("剪切");
JMenuItem copyItem = new JMenuItem("复制");
JMenuItem pasteItem = new JMenuItem("粘贴");
// 添加菜单项到菜单
editMenu.add(cutItem);
editMenu.add(copyItem);
editMenu.add(pasteItem);
// 添加菜单到菜单栏
menuBar.add(fileMenu);
menuBar.add(editMenu);
// 设置窗口的菜单栏
setJMenuBar(menuBar);
// 为退出菜单项添加事件监听器
exitItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
setVisible(true);
}
public static void main(String[] args) {
new SimpleMenuExample();
}
}
运行上面的代码,你将看到一个带有"文件"和"编辑"菜单的窗口。点击"文件"菜单中的"退出"选项将关闭应用程序。
添加快捷键
你可以为菜单项添加键盘快捷键,让用户可以通过键盘组合键快速执行操作:
java
// 为菜单项添加助记符(Alt+字母)
fileMenu.setMnemonic('F'); // Alt+F 打开文件菜单
newItem.setMnemonic('N'); // Alt+F, N 执行新建操作
// 为菜单项添加加速键(Ctrl+字母)
newItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, InputEvent.CTRL_DOWN_MASK));
openItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_DOWN_MASK));
saveItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK));
子菜单
你可以创建层级菜单结构,通过在菜单中添加子菜单:
java
// 创建一个主菜单
JMenu formatMenu = new JMenu("格式");
// 创建一个子菜单
JMenu fontMenu = new JMenu("字体");
// 创建子菜单项
JMenuItem arialItem = new JMenuItem("Arial");
JMenuItem timesItem = new JMenuItem("Times New Roman");
JMenuItem courierItem = new JMenuItem("Courier New");
// 将菜单项添加到子菜单
fontMenu.add(arialItem);
fontMenu.add(timesItem);
fontMenu.add(courierItem);
// 将子菜单添加到主菜单
formatMenu.add(fontMenu);
// 将主菜单添加到菜单栏
menuBar.add(formatMenu);
复选框和单选按钮菜单项
对于需要表示状态的菜单项,可以使用复选框或单选按钮菜单项:
java
// 创建复选框菜单项
JCheckBoxMenuItem gridItem = new JCheckBoxMenuItem("显示网格");
JCheckBoxMenuItem statusBarItem = new JCheckBoxMenuItem("显示状态栏");
// 添加到视图菜单
JMenu viewMenu = new JMenu("视图");
viewMenu.add(gridItem);
viewMenu.add(statusBarItem);
// 创建单选按钮菜单项
JRadioButtonMenuItem smallItem = new JRadioButtonMenuItem("小号字体");
JRadioButtonMenuItem mediumItem = new JRadioButtonMenuItem("中号字体");
JRadioButtonMenuItem largeItem = new JRadioButtonMenuItem("大号字体");
// 创建一个按钮组,确保只有一个选项被选中
ButtonGroup fontSizeGroup = new ButtonGroup();
fontSizeGroup.add(smallItem);
fontSizeGroup.add(mediumItem);
fontSizeGroup.add(largeItem);
// 默认选中中号字体
mediumItem.setSelected(true);
// 添加到格式菜单
JMenu fontSizeMenu = new JMenu("字体大小");
fontSizeMenu.add(smallItem);
fontSizeMenu.add(mediumItem);
fontSizeMenu.add(largeItem);
formatMenu.add(fontSizeMenu);
弹出菜单
弹出菜单(也称为上下文菜单或右键菜单)通常在用户右键点击组件时显示:
java
public class PopupMenuExample extends JFrame {
public PopupMenuExample() {
setTitle("弹出菜单示例");
setSize(400, 300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 创建一个面板
JPanel panel = new JPanel();
// 创建弹出菜单
final JPopupMenu popupMenu = new JPopupMenu();
// 添加菜单项
JMenuItem cutItem = new JMenuItem("剪切");
JMenuItem copyItem = new JMenuItem("复制");
JMenuItem pasteItem = new JMenuItem("粘贴");
popupMenu.add(cutItem);
popupMenu.add(copyItem);
popupMenu.add(pasteItem);
// 为面板添加鼠标监听器
panel.addMouseListener(new MouseAdapter() {
public void mouseReleased(MouseEvent e) {
if (e.isPopupTrigger()) { // 检测是否为弹出菜单触发事件(右键点击)
popupMenu.show(e.getComponent(), e.getX(), e.getY());
}
}
});
add(panel);
setVisible(true);
}
public static void main(String[] args) {
new PopupMenuExample();
}
}
提示
在不同操作系统中,弹出菜单的触发方式可能不同。在Windows中,通常是鼠标右键点击;在macOS中,可能是Control+点击。使用isPopupTrigger()
方法可以确保兼容所有平台。
添加图标
你可以为菜单项添加图标,使界面更直观:
java
// 创建带图标的菜单项
ImageIcon newIcon = new ImageIcon("icons/new.png");
JMenuItem newItem = new JMenuItem("新建", newIcon);
// 或者设置现有菜单项的图标
openItem.setIcon(new ImageIcon("icons/open.png"));
设置菜单项状态
有时需要启用或禁用某些菜单项:
java
// 禁用保存菜单项
saveItem.setEnabled(false);
// 当文档被修改后启用保存菜单项
documentModified = true;
if (documentModified) {
saveItem.setEnabled(true);
}
实际案例:简易文本编辑器
以下是一个简单的文本编辑器示例,展示了如何使用菜单实现常见功能:
java
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
public class SimpleTextEditor extends JFrame {
private JTextArea textArea;
private JFileChooser fileChooser;
private File currentFile;
public SimpleTextEditor() {
setTitle("简易文本编辑器");
setSize(600, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 创建文本区域
textArea = new JTextArea();
textArea.setFont(new Font("SansSerif", Font.PLAIN, 14));
JScrollPane scrollPane = new JScrollPane(textArea);
add(scrollPane, BorderLayout.CENTER);
// 创建文件选择器
fileChooser = new JFileChooser();
// 创建菜单栏
JMenuBar menuBar = new JMenuBar();
// 文件菜单
JMenu fileMenu = new JMenu("文件");
fileMenu.setMnemonic('F');
JMenuItem newItem = new JMenuItem("新建", 'N');
newItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, InputEvent.CTRL_DOWN_MASK));
newItem.addActionListener(e -> newFile());
JMenuItem openItem = new JMenuItem("打开", 'O');
openItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_DOWN_MASK));
openItem.addActionListener(e -> openFile());
JMenuItem saveItem = new JMenuItem("保存", 'S');
saveItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK));
saveItem.addActionListener(e -> saveFile());
JMenuItem exitItem = new JMenuItem("退出", 'X');
exitItem.addActionListener(e -> System.exit(0));
fileMenu.add(newItem);
fileMenu.add(openItem);
fileMenu.add(saveItem);
fileMenu.addSeparator();
fileMenu.add(exitItem);
// 编辑菜单
JMenu editMenu = new JMenu("编辑");
editMenu.setMnemonic('E');
JMenuItem cutItem = new JMenuItem("剪切", 'T');
cutItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, InputEvent.CTRL_DOWN_MASK));
cutItem.addActionListener(e -> textArea.cut());
JMenuItem copyItem = new JMenuItem("复制", 'C');
copyItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_DOWN_MASK));
copyItem.addActionListener(e -> textArea.copy());
JMenuItem pasteItem = new JMenuItem("粘贴", 'P');
pasteItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, InputEvent.CTRL_DOWN_MASK));
pasteItem.addActionListener(e -> textArea.paste());
JMenuItem selectAllItem = new JMenuItem("全选", 'A');
selectAllItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, InputEvent.CTRL_DOWN_MASK));
selectAllItem.addActionListener(e -> textArea.selectAll());
editMenu.add(cutItem);
editMenu.add(copyItem);
editMenu.add(pasteItem);
editMenu.addSeparator();
editMenu.add(selectAllItem);
// 格式菜单
JMenu formatMenu = new JMenu("格式");
formatMenu.setMnemonic('O');
JCheckBoxMenuItem wordWrapItem = new JCheckBoxMenuItem("自动换行");
wordWrapItem.addActionListener(e -> {
textArea.setLineWrap(wordWrapItem.isSelected());
textArea.setWrapStyleWord(wordWrapItem.isSelected());
});
JMenu fontMenu = new JMenu("字体");
ButtonGroup fontGroup = new ButtonGroup();
String[] fonts = {"SansSerif", "Serif", "Monospaced"};
for (String fontName : fonts) {
JRadioButtonMenuItem fontItem = new JRadioButtonMenuItem(fontName);
fontItem.addActionListener(e -> textArea.setFont(new Font(fontName, Font.PLAIN, 14)));
fontGroup.add(fontItem);
fontMenu.add(fontItem);
// 默认选择第一个字体
if (fontName.equals("SansSerif")) {
fontItem.setSelected(true);
}
}
formatMenu.add(wordWrapItem);
formatMenu.addSeparator();
formatMenu.add(fontMenu);
// 将菜单添加到菜单栏
menuBar.add(fileMenu);
menuBar.add(editMenu);
menuBar.add(formatMenu);
// 设置菜单栏
setJMenuBar(menuBar);
// 创建弹出菜单
JPopupMenu popupMenu = new JPopupMenu();
popupMenu.add(new JMenuItem("剪切")).addActionListener(e -> textArea.cut());
popupMenu.add(new JMenuItem("复制")).addActionListener(e -> textArea.copy());
popupMenu.add(new JMenuItem("粘贴")).addActionListener(e -> textArea.paste());
// 为文本区域添加弹出菜单
textArea.addMouseListener(new MouseAdapter() {
public void mouseReleased(MouseEvent e) {
if (e.isPopupTrigger()) {
popupMenu.show(e.getComponent(), e.getX(), e.getY());
}
}
});
setVisible(true);
}
private void newFile() {
textArea.setText("");
currentFile = null;
setTitle("简易文本编辑器");
}
private void openFile() {
int returnVal = fileChooser.showOpenDialog(this);
if (returnVal == JFileChooser.APPROVE_OPTION) {
currentFile = fileChooser.getSelectedFile();
try (BufferedReader reader = new BufferedReader(new FileReader(currentFile))) {
textArea.setText("");
String line;
while ((line = reader.readLine()) != null) {
textArea.append(line + "\n");
}
setTitle("简易文本编辑器 - " + currentFile.getName());
} catch (IOException e) {
JOptionPane.showMessageDialog(this, "打开文件出错: " + e.getMessage(),
"错误", JOptionPane.ERROR_MESSAGE);
}
}
}
private void saveFile() {
if (currentFile == null) {
int returnVal = fileChooser.showSaveDialog(this);
if (returnVal == JFileChooser.APPROVE_OPTION) {
currentFile = fileChooser.getSelectedFile();
} else {
return;
}
}
try (BufferedWriter writer = new BufferedWriter(new FileWriter(currentFile))) {
writer.write(textArea.getText());
setTitle("简易文本编辑器 - " + currentFile.getName());
} catch (IOException e) {
JOptionPane.showMessageDialog(this, "保存文件出错: " + e.getMessage(),
"错误", JOptionPane.ERROR_MESSAGE);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new SimpleTextEditor());
}
}
这个文本编辑器示例展示了如何使用菜单实现常见的文件操作(新建、打开、保存)、编辑操作(剪切、复制、粘贴、全选)以及格式设置(自动换行、字体选择)。
总结
Java菜单系统提供了丰富的功能和灵活的组织方式,允许开发者创建符合用户习惯的交互界面:
- JMenuBar 用于创建位于窗口顶部的菜单栏
- JMenu 用于创建下拉菜单
- JMenuItem 及其子类用于创建可点击的菜单项
- JCheckBoxMenuItem 和 JRadioButtonMenuItem 提供了状态选择功能
- JPopupMenu 用于创建上下文弹出菜单
菜单系统还支持快捷键、图标、分隔符和层级结构等高级功能,使应用程序的用户界面更加直观和易用。
练习
- 创建一个带有"文件"、"编辑"和"帮助"菜单的应用程序,并为菜单项添加适当的快捷键。
- 实现一个画图应用,使用复选框菜单项控制是否显示网格,使用单选按钮菜单项选择绘图颜色。
- 为一个文本区域添加右键菜单,提供文本格式化选项(如大写、小写转换)。
- 扩展上面的文本编辑器,添加"查找"和"替换"功能,并通过菜单项和对话框实现这些功能。
附加资源
通过掌握Java菜单系统,你将能够为你的GUI应用程序添加专业级别的用户交互界面,提高用户体验和应用程序的可用性。