100、Swing 界面开发:工具栏与动作管理

Swing 界面开发:工具栏与动作管理

1. 工具栏概述

工具栏是一种组件,可作为菜单的替代或补充。它包含一系列按钮或其他组件,使用户能够直接访问各种程序选项。例如,工具栏可能包含选择各种字体选项(如加粗、斜体、高亮或下划线)的按钮,用户无需通过菜单即可选择这些选项。通常,工具栏按钮显示图标而非文本,不过两者或其中之一均可使用,并且基于图标的工具栏按钮通常会关联工具提示。

工具栏可以通过拖动放置在窗口的任何一侧,也可以完全拖出窗口,成为浮动工具栏。在 Swing 中,工具栏是 JToolBar 类的实例,其构造函数可用于创建带或不带标题的工具栏,还能指定工具栏的布局(水平或垂直)。

JToolBar 的构造函数如下:

JToolBar()
JToolBar(String title)
JToolBar(int how)
JToolBar(String title, int how)
  • 第一个构造函数创建一个无标题的水平工具栏。
  • 第二个构造函数创建一个具有指定标题的水平工具栏,标题仅在工具栏被拖出窗口时显示。
  • 第三个构造函数创建一个根据 how 参数指定方向的工具栏, how 的值必须为 JToolBar.VERTICAL JToolBar.HORIZONTAL
  • 第四个构造函数创建一个具有指定标题和指定方向的工具栏。

工具栏通常与使用边界布局的窗口一起使用,原因有二:一是允许工具栏初始定位在四个边界位置之一,通常使用顶部位置;二是允许工具栏拖动到窗口的任何一侧。

添加按钮或其他组件到工具栏的方式与添加到菜单栏类似,只需调用 add() 方法,组件将按添加顺序显示在工具栏中。创建工具栏后,应将其添加到窗口容器,而不是菜单栏(如果存在)。通常,会将工具栏添加到边界布局的顶部(即北部)位置,使用水平方向,受影响的组件添加到边界布局的中心。

2. 在程序中添加工具栏

为了说明工具栏的使用,我们将在 MenuDemo 程序中添加一个工具栏,该工具栏将提供三个调试选项:设置断点、清除断点和恢复程序执行。添加工具栏需要三个步骤:

  1. 从程序中移除以下代码行:
jfrm.setLayout(new FlowLayout());

移除该行后, JFrame 自动使用边界布局。

  1. 由于使用了 BorderLayout ,将添加标签 jlab 到框架的代码行修改如下:
jfrm.add(jlab, BorderLayout.CENTER);

这行代码明确将 jlab 添加到边界布局的中心。虽然在使用边界布局时,默认情况下组件会添加到中心,但明确指定中心位置可以让阅读代码的人清楚地知道使用了边界布局,并且 jlab 位于中心。

  1. 添加以下代码创建调试工具栏:
// Create a Debug toolbar.
JToolBar jtb = new JToolBar("Debug");

// Load the images.
ImageIcon set = new ImageIcon("setBP.gif");
ImageIcon clear = new ImageIcon("clearBP.gif");
ImageIcon resume = new ImageIcon("resume.gif");

// Create the toolbar buttons.
JButton jbtnSet = new JButton(set);
jbtnSet.setActionCommand("Set Breakpoint");
jbtnSet.setToolTipText("Set Breakpoint");

JButton jbtnClear = new JButton(clear);
jbtnClear.setActionCommand("Clear Breakpoint");
jbtnClear.setToolTipText("Clear Breakpoint");

JButton jbtnResume = new JButton(resume);
jbtnResume.setActionCommand("Resume");
jbtnResume.setToolTipText("Resume");

// Add the buttons to the toolbar.
jtb.add(jbtnSet);
jtb.add(jbtnClear);
jtb.add(jbtnResume);

// Add the toolbar to the north position of
// the content pane.
jfrm.add(jtb, BorderLayout.NORTH);

这段代码首先创建一个名为 “Debug” 的 JToolBar ,然后加载用于工具栏按钮的图像,接着创建三个工具栏按钮,为每个按钮设置动作命令和工具提示,将按钮添加到工具栏,最后将工具栏添加到框架边界布局的北部。

最后,添加工具栏的动作监听器:

// Add the toolbar action listeners.
jbtnSet.addActionListener(this);
jbtnClear.addActionListener(this);
jbtnResume.addActionListener(this);

每次用户按下工具栏按钮时,都会触发一个动作事件,该事件将以与其他菜单相关事件相同的方式处理。

3. 使用动作管理组件

在很多情况下,工具栏和菜单项包含共同的项目。例如,前面示例中的调试工具栏提供的功能也可以通过菜单选择来实现。在这种情况下,选择某个选项(如设置断点)会导致相同的操作发生,无论使用的是菜单还是工具栏。此外,工具栏按钮和菜单项很可能使用相同的图标,并且当工具栏按钮禁用时,相应的菜单项也需要禁用。这种情况通常会导致大量重复且相互依赖的代码,而 Swing 提供了一种解决方案:动作。

动作是 Action 接口的实例, Action 扩展了 ActionListener 接口,并提供了一种将状态信息与 actionPerformed() 事件处理程序相结合的方法。这种结合允许一个动作管理两个或更多组件,例如,一个动作可以集中控制和处理工具栏按钮和菜单项,而无需重复代码。

Action 除了继承的 actionPerformed() 方法外,还定义了几个自己的方法,其中一个特别有用的是 putValue() 方法,用于设置与动作相关的各种属性的值:

void putValue(String key, Object val)

它将 val 分配给由 key 指定的属性。 Action 还提供了 getValue() 方法来获取指定的属性:

Object getValue(String key)

putValue() getValue() 使用的键值如下表所示:
| 键值 | 描述 |
| — | — |
| static final String ACCELERATOR_KEY | 表示加速器属性,加速器指定为 KeyStroke 对象 |
| static final String ACTION_COMMAND_KEY | 表示动作命令属性,动作命令指定为字符串 |
| static final String DISPLAYED_MNEMONIC_INDEX_KEY | 表示作为助记符显示的字符的索引,是一个 Integer 值 |
| static final String LARGE_ICON_KEY | 表示与动作关联的大图标,图标指定为 Icon 类型的对象 |
| static final String LONG_DESCRIPTION | 表示动作的长描述,描述指定为字符串 |
| static final String MNEMONIC_KEY | 表示助记符属性,助记符指定为 KeyEvent 常量 |
| static final String NAME | 表示动作的名称,也是与该动作关联的按钮或菜单项的名称,名称指定为字符串 |
| static final String SELECTED_KEY | 表示选择状态,如果设置,则该项被选中,状态由布尔值表示 |
| static final String SHORT_DESCRIPTION | 表示与动作关联的工具提示文本,工具提示文本指定为字符串 |
| static final String SMALL_ICON | 表示与动作关联的图标,图标指定为 Icon 类型的对象 |

动作的启用或禁用状态不能通过 putValue() getValue() 访问,需要使用 setEnabled() isEnabled() 方法:

void setEnabled(boolean enabled)
boolean isEnabled()

如果 enabled true ,则动作启用;否则,动作禁用。如果动作启用, isEnabled() 返回 true ;否则返回 false

虽然可以自己实现 Action 接口的所有方法,但通常不需要这样做。Swing 提供了一个部分实现类 AbstractAction ,可以扩展该类,只需实现 actionPerformed() 方法,其他 Action 方法由 AbstractAction 提供。 AbstractAction 提供了三个构造函数,这里使用的是:

AbstractAction(String name, Icon image)

它构造一个具有指定名称和图标的 AbstractAction

要将动作添加到 JToolBar ,使用 add() 方法的这个版本:

void add(Action actObj)

这里, actObj 是要添加到工具栏的动作,由 actObj 定义的属性用于创建工具栏按钮。要从动作创建菜单项,使用 JMenuItem 的构造函数:

JMenuItem(Action actObj)

这里, actObj 是根据其属性构造菜单项的动作。

为了说明动作的好处,我们将使用动作来管理前面创建的调试工具栏,并在 Options 主菜单下添加一个调试子菜单,该子菜单将包含与调试工具栏相同的选项:设置断点、清除断点和恢复。支持工具栏中这些项目的动作也将支持菜单中的这些项目,从而避免了重复代码。

以下是创建动作管理调试工具栏和菜单的步骤:
1. 创建一个名为 DebugAction 的内部类,扩展 AbstractAction

// A class to create an action for the Debug menu
// and toolbar.
class DebugAction extends AbstractAction {
  public DebugAction(String name, Icon image, int mnem,
                    int accel, String tTip) {
    super(name, image);
    putValue(ACCELERATOR_KEY,
             KeyStroke.getKeyStroke(accel,
                                    InputEvent.CTRL_DOWN_MASK));
    putValue(MNEMONIC_KEY, new Integer(mnem));
    putValue(SHORT_DESCRIPTION, tTip);
  }

  // Handle events for both the toolbar and the
  // Debug menu.
  public void actionPerformed(ActionEvent ae) {
    String comStr = ae.getActionCommand();

    jlab.setText(comStr + " Selected");

    // Toggle the enabled status of the
    // Set and Clear Breakpoint options.
    if(comStr.equals("Set Breakpoint")) {
      clearAct.setEnabled(true);
      setAct.setEnabled(false);
    } else if(comStr.equals("Clear Breakpoint")) {
      clearAct.setEnabled(false);
      setAct.setEnabled(true);
    }
  }
}

DebugAction 类的构造函数接受五个参数,用于指定名称、图标、助记符、加速器和工具提示。 actionPerformed() 方法处理工具栏和调试菜单的事件,根据动作命令更新标签文本,并切换设置和清除断点选项的启用状态。

  1. MenuDemo 类中添加 DebugAction 实例变量:
DebugAction setAct;
DebugAction clearAct;
DebugAction resumeAct;
  1. 创建表示调试选项的 ImageIcon 对象:
// Load the images for the actions.
ImageIcon setIcon = new ImageIcon("setBP.gif");
ImageIcon clearIcon = new ImageIcon("clearBP.gif");
ImageIcon resumeIcon = new ImageIcon("resume.gif");
  1. 创建管理调试选项的动作:
// Create actions.
setAct =
  new DebugAction("Set Breakpoint",
                  setIcon,
                  KeyEvent.VK_S,
                  KeyEvent.VK_B,
                  "Set a break point.");

clearAct =
  new DebugAction("Clear Breakpoint",
                  clearIcon,
                  KeyEvent.VK_C,
                  KeyEvent.VK_L,
                  "Clear a break point.");

resumeAct =
  new DebugAction("Resume",
                  resumeIcon,
                  KeyEvent.VK_R,
                  KeyEvent.VK_R,
                  "Resume execution after breakpoint.");

// Initially disable the Clear Breakpoint option.
clearAct.setEnabled(false);

注意,设置断点的加速器是 B ,清除断点的加速器是 L ,这是因为 S C 已经被文件菜单用于保存和关闭操作,但它们仍可作为助记符,因为每个助记符是局部于其自己的菜单的。此外,清除断点的动作初始时是禁用的,只有在设置了断点后才会启用。

  1. 使用动作创建工具栏按钮并添加到工具栏:
// Create the toolbar buttons by using the actions.
JButton jbtnSet = new JButton(setAct);
JButton jbtnClear = new JButton(clearAct);
JButton jbtnResume = new JButton(resumeAct);

// Create a Debug toolbar.
JToolBar jtb = new JToolBar("Breakpoints");

// Add the buttons to the toolbar.
jtb.add(jbtnSet);
jtb.add(jbtnClear);
jtb.add(jbtnResume);

// Add the toolbar to the north position of
// the content pane.
jfrm.add(jtb, BorderLayout.NORTH);
  1. 创建调试菜单:
// Now, create a Debug menu that goes under the Options
// menu bar item. Use the actions to create the items.
JMenu jmDebug = new JMenu("Debug");
JMenuItem jmiSetBP = new JMenuItem(setAct);
JMenuItem jmiClearBP = new JMenuItem(clearAct);
JMenuItem jmiResume = new JMenuItem(resumeAct);
jmDebug.add(jmiSetBP);
jmDebug.add(jmiClearBP);
jmDebug.add(jmiResume);
jmOptions.add(jmDebug);

通过这些步骤,创建的动作将用于管理调试菜单和工具栏,更改动作的属性(如禁用它)将影响该动作的所有使用。

4. 完整的 MenuDemo 程序

以下是包含所有添加和增强功能的完整 MenuDemo 程序:

// The complete MenuDemo program.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

class MenuDemo implements ActionListener {

  JLabel jlab;

  JMenuBar jmb;

  JToolBar jtb;

  JPopupMenu jpu;

  DebugAction setAct;
  DebugAction clearAct;
  DebugAction resumeAct;

  MenuDemo() {
    // Create a new JFrame container.
    JFrame jfrm = new JFrame("Complete Menu Demo");

    // Use default border layout.

    // Give the frame an initial size.
    jfrm.setSize(360, 200);

    // Terminate the program when the user closes the application.
    jfrm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    // Create a label that will display the menu selection.
    jlab = new JLabel();

    // Create the menu bar.
    jmb = new JMenuBar();

    // Make the File menu.
    makeFileMenu();

    // Construct the Debug actions.
    makeActions();

    // Make the toolbar.
    makeToolBar();

    // Make the Options menu.
    makeOptionsMenu();

    // Make the Help menu.
    makeHelpMenu();

    // Make the Edit popup menu.
    makeEditPUMenu();

    // Add a listener for the popup trigger.
    jfrm.addMouseListener(new MouseAdapter() {
      public void mousePressed(MouseEvent me) {
        if(me.isPopupTrigger())
          jpu.show(me.getComponent(), me.getX(), me.getY());
      }
      public void mouseReleased(MouseEvent me) {
        if(me.isPopupTrigger())
          jpu.show(me.getComponent(), me.getX(), me.getY());
      }
    });

    // Add the label to the center of the content pane.
    jfrm.add(jlab, SwingConstants.CENTER);

    // Add the toolbar to the north position of
    // the content pane.
    jfrm.add(jtb, BorderLayout.NORTH);

    // Add the menu bar to the frame.
    jfrm.setJMenuBar(jmb);

    // Display the frame.
    jfrm.setVisible(true);
  }

  // Handle menu item action events.
  // This does NOT handle events generated
  // by the Debug options.
  public void actionPerformed(ActionEvent ae) {
    String comStr = ae.getActionCommand();

    // If user chooses Exit, then exit the program.
    if(comStr.equals("Exit")) System.exit(0);

    // Otherwise, display the selection.
    jlab.setText(comStr + " Selected");
  }

  // An action class for the Debug menu
  // and toolbar.
  class DebugAction extends AbstractAction {
    public DebugAction(String name, Icon image, int mnem,
                       int accel, String tTip) {
      super(name, image);
      putValue(ACCELERATOR_KEY,
               KeyStroke.getKeyStroke(accel,
                                      InputEvent.CTRL_DOWN_MASK));
      putValue(MNEMONIC_KEY, new Integer(mnem));
      putValue(SHORT_DESCRIPTION, tTip);
    }

    // Handle events for both the toolbar and the
    // Debug menu.
    public void actionPerformed(ActionEvent ae) {
      String comStr = ae.getActionCommand();

      jlab.setText(comStr + " Selected");

      // Toggle the enabled status of the
      // Set and Clear Breakpoint options.
      if(comStr.equals("Set Breakpoint")) {
        clearAct.setEnabled(true);
        setAct.setEnabled(false);
      } else if(comStr.equals("Clear Breakpoint")) {
        clearAct.setEnabled(false);
        setAct.setEnabled(true);
      }
    }
  }

  // Create the File menu with mnemonics and accelerators.
  void makeFileMenu() {
    JMenu jmFile = new JMenu("File");
    jmFile.setMnemonic(KeyEvent.VK_F);

    JMenuItem jmiOpen = new JMenuItem("Open",
                                      KeyEvent.VK_O);
    jmiOpen.setAccelerator(
              KeyStroke.getKeyStroke(KeyEvent.VK_O,
                                     InputEvent.CTRL_DOWN_MASK));

    JMenuItem jmiClose = new JMenuItem("Close",
                                       KeyEvent.VK_C);
    jmiClose.setAccelerator(
              KeyStroke.getKeyStroke(KeyEvent.VK_C,
                                     InputEvent.CTRL_DOWN_MASK));

    JMenuItem jmiSave = new JMenuItem("Save",
                                      KeyEvent.VK_S);
    jmiSave.setAccelerator(
              KeyStroke.getKeyStroke(KeyEvent.VK_S,
                                     InputEvent.CTRL_DOWN_MASK));

    JMenuItem jmiExit = new JMenuItem("Exit",
                                      KeyEvent.VK_E);
    jmiExit.setAccelerator(
              KeyStroke.getKeyStroke(KeyEvent.VK_E,
                                     InputEvent.CTRL_DOWN_MASK));

    jmFile.add(jmiOpen);
    jmFile.add(jmiClose);
    jmFile.add(jmiSave);
    jmFile.addSeparator();
    jmFile.add(jmiExit);
    jmb.add(jmFile);

    // Add the action listeners for the File menu.
    jmiOpen.addActionListener(this);
    jmiClose.addActionListener(this);
    jmiSave.addActionListener(this);
    jmiExit.addActionListener(this);
  }

  // Create the Options menu.
  void makeOptionsMenu() {
    JMenu jmOptions = new JMenu("Options");

    // Create the Colors submenu.
    JMenu jmColors = new JMenu("Colors");

    // Use check boxes for colors. This allows
    // the user to select more than one color.
    JCheckBoxMenuItem jmiRed = new JCheckBoxMenuItem("Red");
    JCheckBoxMenuItem jmiGreen = new JCheckBoxMenuItem("Green");
    JCheckBoxMenuItem jmiBlue = new JCheckBoxMenuItem("Blue");

    // Add the items to the Colors menu.
    jmColors.add(jmiRed);
    jmColors.add(jmiGreen);
    jmColors.add(jmiBlue);
    jmOptions.add(jmColors);

    // Create the Priority submenu.
    JMenu jmPriority = new JMenu("Priority");

    // Use radio buttons for the priority setting.
    // This lets the menu show which priority is used
    // but also ensures that one and only one priority
    // can be selected at any one time. Notice that
    // the High radio button is initially selected.
    JRadioButtonMenuItem jmiHigh =
      new JRadioButtonMenuItem("High", true);
    JRadioButtonMenuItem jmiLow =
      new JRadioButtonMenuItem("Low");

    // Add the items to the Priority menu.
    jmPriority.add(jmiHigh);
    jmPriority.add(jmiLow);
    jmOptions.add(jmPriority);

    // Create a button group for the radio button
    //  menu items.
    ButtonGroup bg = new ButtonGroup();
    bg.add(jmiHigh);
    bg.add(jmiLow);

    // Now, create a Debug submenu that goes under
    // the Options menu bar item. Use actions to
    // create the items.
    JMenu jmDebug = new JMenu("Debug");
    JMenuItem jmiSetBP = new JMenuItem(setAct);
    JMenuItem jmiClearBP = new JMenuItem(clearAct);
    JMenuItem jmiResume = new JMenuItem(resumeAct);

    // Add the items to the Debug menu.
    jmDebug.add(jmiSetBP);
    jmDebug.add(jmiClearBP);
    jmDebug.add(jmiResume);
    jmOptions.add(jmDebug);

    // Create the Reset menu item.
    JMenuItem jmiReset = new JMenuItem("Reset");
    jmOptions.addSeparator();
    jmOptions.add(jmiReset);

    // Finally, add the entire options menu to
    // the menu bar
    jmb.add(jmOptions);

    // Add the action listeners for the Options menu,
    // except for those supported by the Debug menu.
    jmiRed.addActionListener(this);
    jmiGreen.addActionListener(this);
    jmiBlue.addActionListener(this);
    jmiHigh.addActionListener(this);
    jmiLow.addActionListener(this);
    jmiReset.addActionListener(this);
  }

  // Create the Help menu.
  void makeHelpMenu() {
    JMenu jmHelp = new JMenu("Help");

    // Add an icon to the About menu item.
    ImageIcon icon = new ImageIcon("AboutIcon.gif");

    JMenuItem jmiAbout = new JMenuItem("About", icon);
    jmiAbout.setToolTipText("Info about the MenuDemo program.");
    jmHelp.add(jmiAbout);
    jmb.add(jmHelp);

    // Add action listener for About.
    jmiAbout.addActionListener(this);
  }

  // Construct the actions needed by the Debug menu
  // and toolbar.
  void makeActions() {
    // Load the images for the actions.
    ImageIcon setIcon = new ImageIcon("setBP.gif");
    ImageIcon clearIcon = new ImageIcon("clearBP.gif");
    ImageIcon resumeIcon = new ImageIcon("resume.gif");

    // Create actions.
    setAct =
      new DebugAction("Set Breakpoint",
                      setIcon,
                      KeyEvent.VK_S,
                      KeyEvent.VK_B,
                      "Set a break point.");

    clearAct =
      new DebugAction("Clear Breakpoint",
                      clearIcon,
                      KeyEvent.VK_C,
                      KeyEvent.VK_L,
                      "Clear a break point.");

    resumeAct =
      new DebugAction("Resume",
                      resumeIcon,
                      KeyEvent.VK_R,
                      KeyEvent.VK_R,
                      "Resume execution after breakpoint.");

    // Initially disable the Clear Breakpoint option.
    clearAct.setEnabled(false);
  }

  // Create the Debug toolbar.
  void makeToolBar() {
    // Create the toolbar buttons by using the actions.
    JButton jbtnSet = new JButton(setAct);
    JButton jbtnClear = new JButton(clearAct);
    JButton jbtnResume = new JButton(resumeAct);

    // Create the Debug toolbar.
    jtb = new JToolBar("Breakpoints");

    // Add the buttons to the toolbar.
    jtb.add(jbtnSet);
    jtb.add(jbtnClear);
    jtb.add(jbtnResume);
  }
}

通过上述代码和步骤,我们可以看到如何在 Swing 应用程序中使用工具栏和动作来管理界面组件,提高代码的可维护性和复用性。

Swing 界面开发:工具栏与动作管理

5. 程序各部分详细解析
5.1 主类 MenuDemo

MenuDemo 类实现了 ActionListener 接口,用于处理菜单项的动作事件。其构造函数完成了界面的初始化工作:
- 创建 JFrame 窗口,并设置标题、大小和关闭操作。
- 创建用于显示菜单选择的标签 jlab
- 创建菜单栏 jmb
- 调用各个方法创建菜单、工具栏和动作。
- 添加鼠标监听器以处理弹出菜单的触发事件。
- 将标签添加到内容面板的中心,工具栏添加到北部,菜单栏设置到框架上,并显示窗口。

class MenuDemo implements ActionListener {

  JLabel jlab;
  JMenuBar jmb;
  JToolBar jtb;
  JPopupMenu jpu;
  DebugAction setAct;
  DebugAction clearAct;
  DebugAction resumeAct;

  MenuDemo() {
    // Create a new JFrame container.
    JFrame jfrm = new JFrame("Complete Menu Demo");

    // Use default border layout.

    // Give the frame an initial size.
    jfrm.setSize(360, 200);

    // Terminate the program when the user closes the application.
    jfrm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    // Create a label that will display the menu selection.
    jlab = new JLabel();

    // Create the menu bar.
    jmb = new JMenuBar();

    // Make the File menu.
    makeFileMenu();

    // Construct the Debug actions.
    makeActions();

    // Make the toolbar.
    makeToolBar();

    // Make the Options menu.
    makeOptionsMenu();

    // Make the Help menu.
    makeHelpMenu();

    // Make the Edit popup menu.
    makeEditPUMenu();

    // Add a listener for the popup trigger.
    jfrm.addMouseListener(new MouseAdapter() {
      public void mousePressed(MouseEvent me) {
        if(me.isPopupTrigger())
          jpu.show(me.getComponent(), me.getX(), me.getY());
      }
      public void mouseReleased(MouseEvent me) {
        if(me.isPopupTrigger())
          jpu.show(me.getComponent(), me.getX(), me.getY());
      }
    });

    // Add the label to the center of the content pane.
    jfrm.add(jlab, SwingConstants.CENTER);

    // Add the toolbar to the north position of
    // the content pane.
    jfrm.add(jtb, BorderLayout.NORTH);

    // Add the menu bar to the frame.
    jfrm.setJMenuBar(jmb);

    // Display the frame.
    jfrm.setVisible(true);
  }

  // Handle menu item action events.
  // This does NOT handle events generated
  // by the Debug options.
  public void actionPerformed(ActionEvent ae) {
    String comStr = ae.getActionCommand();

    // If user chooses Exit, then exit the program.
    if(comStr.equals("Exit")) System.exit(0);

    // Otherwise, display the selection.
    jlab.setText(comStr + " Selected");
  }
}
5.2 DebugAction

DebugAction 类继承自 AbstractAction ,用于处理调试工具栏和调试菜单的动作事件。其构造函数接受名称、图标、助记符、加速器和工具提示作为参数,并设置相应的属性。 actionPerformed 方法根据用户的操作更新标签文本,并切换设置和清除断点选项的启用状态。

// An action class for the Debug menu
// and toolbar.
class DebugAction extends AbstractAction {
  public DebugAction(String name, Icon image, int mnem,
                     int accel, String tTip) {
    super(name, image);
    putValue(ACCELERATOR_KEY,
             KeyStroke.getKeyStroke(accel,
                                    InputEvent.CTRL_DOWN_MASK));
    putValue(MNEMONIC_KEY, new Integer(mnem));
    putValue(SHORT_DESCRIPTION, tTip);
  }

  // Handle events for both the toolbar and the
  // Debug menu.
  public void actionPerformed(ActionEvent ae) {
    String comStr = ae.getActionCommand();

    jlab.setText(comStr + " Selected");

    // Toggle the enabled status of the
    // Set and Clear Breakpoint options.
    if(comStr.equals("Set Breakpoint")) {
      clearAct.setEnabled(true);
      setAct.setEnabled(false);
    } else if(comStr.equals("Clear Breakpoint")) {
      clearAct.setEnabled(false);
      setAct.setEnabled(true);
    }
  }
}
5.3 makeFileMenu 方法

该方法用于创建文件菜单,包含打开、关闭、保存和退出等选项。为每个菜单项设置了助记符和加速器,并添加了动作监听器。

// Create the File menu with mnemonics and accelerators.
void makeFileMenu() {
  JMenu jmFile = new JMenu("File");
  jmFile.setMnemonic(KeyEvent.VK_F);

  JMenuItem jmiOpen = new JMenuItem("Open",
                                    KeyEvent.VK_O);
  jmiOpen.setAccelerator(
            KeyStroke.getKeyStroke(KeyEvent.VK_O,
                                   InputEvent.CTRL_DOWN_MASK));

  JMenuItem jmiClose = new JMenuItem("Close",
                                     KeyEvent.VK_C);
  jmiClose.setAccelerator(
            KeyStroke.getKeyStroke(KeyEvent.VK_C,
                                   InputEvent.CTRL_DOWN_MASK));

  JMenuItem jmiSave = new JMenuItem("Save",
                                    KeyEvent.VK_S);
  jmiSave.setAccelerator(
            KeyStroke.getKeyStroke(KeyEvent.VK_S,
                                   InputEvent.CTRL_DOWN_MASK));

  JMenuItem jmiExit = new JMenuItem("Exit",
                                    KeyEvent.VK_E);
  jmiExit.setAccelerator(
            KeyStroke.getKeyStroke(KeyEvent.VK_E,
                                   InputEvent.CTRL_DOWN_MASK));

  jmFile.add(jmiOpen);
  jmFile.add(jmiClose);
  jmFile.add(jmiSave);
  jmFile.addSeparator();
  jmFile.add(jmiExit);
  jmb.add(jmFile);

  // Add the action listeners for the File menu.
  jmiOpen.addActionListener(this);
  jmiClose.addActionListener(this);
  jmiSave.addActionListener(this);
  jmiExit.addActionListener(this);
}
5.4 makeOptionsMenu 方法

此方法创建选项菜单,包含颜色和优先级子菜单,以及调试子菜单。颜色子菜单使用复选框,允许用户选择多种颜色;优先级子菜单使用单选按钮,确保用户只能选择一个优先级。调试子菜单使用之前创建的动作来创建菜单项。

// Create the Options menu.
void makeOptionsMenu() {
  JMenu jmOptions = new JMenu("Options");

  // Create the Colors submenu.
  JMenu jmColors = new JMenu("Colors");

  // Use check boxes for colors. This allows
  // the user to select more than one color.
  JCheckBoxMenuItem jmiRed = new JCheckBoxMenuItem("Red");
  JCheckBoxMenuItem jmiGreen = new JCheckBoxMenuItem("Green");
  JCheckBoxMenuItem jmiBlue = new JCheckBoxMenuItem("Blue");

  // Add the items to the Colors menu.
  jmColors.add(jmiRed);
  jmColors.add(jmiGreen);
  jmColors.add(jmiBlue);
  jmOptions.add(jmColors);

  // Create the Priority submenu.
  JMenu jmPriority = new JMenu("Priority");

  // Use radio buttons for the priority setting.
  // This lets the menu show which priority is used
  // but also ensures that one and only one priority
  // can be selected at any one time. Notice that
  // the High radio button is initially selected.
  JRadioButtonMenuItem jmiHigh =
    new JRadioButtonMenuItem("High", true);
  JRadioButtonMenuItem jmiLow =
    new JRadioButtonMenuItem("Low");

  // Add the items to the Priority menu.
  jmPriority.add(jmiHigh);
  jmPriority.add(jmiLow);
  jmOptions.add(jmPriority);

  // Create a button group for the radio button
  //  menu items.
  ButtonGroup bg = new ButtonGroup();
  bg.add(jmiHigh);
  bg.add(jmiLow);

  // Now, create a Debug submenu that goes under
  // the Options menu bar item. Use actions to
  // create the items.
  JMenu jmDebug = new JMenu("Debug");
  JMenuItem jmiSetBP = new JMenuItem(setAct);
  JMenuItem jmiClearBP = new JMenuItem(clearAct);
  JMenuItem jmiResume = new JMenuItem(resumeAct);

  // Add the items to the Debug menu.
  jmDebug.add(jmiSetBP);
  jmDebug.add(jmiClearBP);
  jmDebug.add(jmiResume);
  jmOptions.add(jmDebug);

  // Create the Reset menu item.
  JMenuItem jmiReset = new JMenuItem("Reset");
  jmOptions.addSeparator();
  jmOptions.add(jmiReset);

  // Finally, add the entire options menu to
  // the menu bar
  jmb.add(jmOptions);

  // Add the action listeners for the Options menu,
  // except for those supported by the Debug menu.
  jmiRed.addActionListener(this);
  jmiGreen.addActionListener(this);
  jmiBlue.addActionListener(this);
  jmiHigh.addActionListener(this);
  jmiLow.addActionListener(this);
  jmiReset.addActionListener(this);
}
5.5 makeHelpMenu 方法

该方法创建帮助菜单,包含一个关于菜单项,并为其添加了图标和工具提示。

// Create the Help menu.
void makeHelpMenu() {
  JMenu jmHelp = new JMenu("Help");

  // Add an icon to the About menu item.
  ImageIcon icon = new ImageIcon("AboutIcon.gif");

  JMenuItem jmiAbout = new JMenuItem("About", icon);
  jmiAbout.setToolTipText("Info about the MenuDemo program.");
  jmHelp.add(jmiAbout);
  jmb.add(jmHelp);

  // Add action listener for About.
  jmiAbout.addActionListener(this);
}
5.6 makeActions 方法

此方法用于创建调试动作,加载相应的图标,创建设置断点、清除断点和恢复执行的动作,并初始禁用清除断点选项。

// Construct the actions needed by the Debug menu
// and toolbar.
void makeActions() {
  // Load the images for the actions.
  ImageIcon setIcon = new ImageIcon("setBP.gif");
  ImageIcon clearIcon = new ImageIcon("clearBP.gif");
  ImageIcon resumeIcon = new ImageIcon("resume.gif");

  // Create actions.
  setAct =
    new DebugAction("Set Breakpoint",
                    setIcon,
                    KeyEvent.VK_S,
                    KeyEvent.VK_B,
                    "Set a break point.");

  clearAct =
    new DebugAction("Clear Breakpoint",
                    clearIcon,
                    KeyEvent.VK_C,
                    KeyEvent.VK_L,
                    "Clear a break point.");

  resumeAct =
    new DebugAction("Resume",
                    resumeIcon,
                    KeyEvent.VK_R,
                    KeyEvent.VK_R,
                    "Resume execution after breakpoint.");

  // Initially disable the Clear Breakpoint option.
  clearAct.setEnabled(false);
}
5.7 makeToolBar 方法

该方法使用之前创建的动作创建调试工具栏按钮,并将按钮添加到工具栏,最后将工具栏添加到窗口的北部。

// Create the Debug toolbar.
void makeToolBar() {
  // Create the toolbar buttons by using the actions.
  JButton jbtnSet = new JButton(setAct);
  JButton jbtnClear = new JButton(clearAct);
  JButton jbtnResume = new JButton(resumeAct);

  // Create the Debug toolbar.
  jtb = new JToolBar("Breakpoints");

  // Add the buttons to the toolbar.
  jtb.add(jbtnSet);
  jtb.add(jbtnClear);
  jtb.add(jbtnResume);
}
6. 总结

通过上述内容,我们详细介绍了在 Swing 界面开发中如何使用工具栏和动作来管理界面组件。工具栏作为菜单的补充,为用户提供了更便捷的操作方式,用户可以直接通过工具栏按钮访问常用功能。而动作机制则解决了工具栏和菜单项之间代码重复和相互依赖的问题,通过一个动作可以同时管理多个组件,提高了代码的可维护性和复用性。

在实际开发中,我们可以根据具体需求对上述代码进行扩展和修改。例如,可以添加更多的菜单项和工具栏按钮,或者修改动作的处理逻辑以实现更复杂的功能。同时,合理使用助记符、加速器和工具提示等功能,可以提升用户体验,让用户更方便地使用应用程序。

以下是整个开发流程的 mermaid 流程图:

graph LR
    A[创建 JFrame 窗口] --> B[创建菜单栏]
    B --> C[创建文件菜单]
    B --> D[创建选项菜单]
    B --> E[创建帮助菜单]
    A --> F[创建调试动作]
    F --> G[创建调试工具栏]
    A --> H[创建标签显示选择结果]
    A --> I[添加鼠标监听器处理弹出菜单]
    G --> J[将工具栏添加到窗口北部]
    C --> K[添加文件菜单动作监听器]
    D --> L[添加选项菜单动作监听器]
    E --> M[添加帮助菜单动作监听器]
    G --> N[添加工具栏动作监听器]
    H --> O[将标签添加到窗口中心]
    B --> P[将菜单栏添加到窗口]
    A --> Q[显示窗口]

通过这个流程图,我们可以清晰地看到整个程序的开发步骤和组件之间的关系,有助于我们更好地理解和维护代码。希望本文能对 Swing 界面开发的初学者有所帮助,让大家能够更轻松地创建出功能丰富、用户体验良好的应用程序。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值