监听所有菜单项的 JFrame 动作监听器?

JFrame Action Listener that listens to all menu items?

所以我设置了一个 JFrame,其中包含一个菜单,该菜单的当前结构看起来大致如下:

File
  Exit
Pages
  Reviews
    A
    B
    C
Help
  About

我想创建一个动作侦听器,它只侦听评论下的菜单项。这是否可能(如果可能,如何),或者我是否必须创建一个通用侦听器并检查它是否是其中一项?

是的,有可能:

  • 将菜单项存储为字段
  • 向每个菜单项添加相同的 ActionListener
  • 在侦听器中检查来源以了解单击了哪个项目。

应该看起来像:

public class YourFrame extends JFrame implements ActionListener {

   private final JMenuItem menuA, menuB;

   public YourFrame(){
      super("Your app");
      JMenuBar menuBar = new JMenuBar();
      JMenu menuReviews = new JMenu("Reviews");
      menuA = new JMenuItem("A");
      menuB = new JMenuItem("B");
      ...
      menuReviews.add(menuA);
      menuReviews.add(menuB);
      menuBar.add(menuReviews);
      setJMenuBar(menuBar);
      ...
      menuA.addActionListener(this);
      menuB.addActionListener(this);
      ...
   }

   public void actionPerformed(ActionEvent event){
      if(event.getSource()==menuA){
         System.out.println("Menu A clicked");
         ...
      }else if(event.getSource()==menuB){
         System.out.println("Menu B clicked");
         ...
      }
   }

}

注意这里我让JFrame实现了ActionListener,但这只是为了方便。您可以使用专用 class,或在构造函数中创建的匿名 class:

ActionListener reviewsListener = new ActionListener(){
   public void actionPerformed(ActionEvent event){
      if(event.getSource()==menuA){
         System.out.println("Menu A clicked");
         ...
      }else if(event.getSource()==menuB){
         System.out.println("Menu B clicked");
         ...
      }
   }
};
menuA.addActionListener(reviewsListener);
menuB.addActionListener(reviewsListener);

如果你想更多地整合这个过程,我也可以建议扩展 JMenu,这样你就可以将它传递给你的动作侦听器,并系统地将它添加到新的菜单项中。

public class YourJMenu extends JMenu {
   private ActionListener listener;
   public YourJMenu(String name, ActionListener listener){
      super(name);
      this.listener = listener;
   }
   @Override
   public JMenuItem add(JMenuItem item){
      item.addActionListener(listener);
      return super.add(item);
   }
}

有了这个,你只需要写:

JMenu menuReviews = new YourJMenu("Reviews", this);

并放下:

menuA.addActionListener(this);
menuB.addActionListener(this);

使用一种常见的方法,我们可以将动作侦听器添加到菜单下的所有菜单项。下面是一个示例代码。

public class MenuItemEvent {
    JFrame objFrm = new JFrame("Menu event demo");
    JMenuBar mBar;
    JMenu mnu;
    JMenuItem mnuItem1, mnuItem2, mnuItem3;
    public void show() {
        objFrm.setSize(300, 300);
        mBar = new JMenuBar();
        mnu = new JMenu("Reviews");
        mBar.add(mnu);

        mnuItem1 = new JMenuItem("A");
        mnu.add(mnuItem1);

        mnuItem2 = new JMenuItem("B");
        mnu.add(mnuItem2);

        mnuItem3 = new JMenuItem("C");
        mnu.add(mnuItem3);

        //method call
        fnAddActionListener(mnu);

        objFrm.setJMenuBar(mBar);
        objFrm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        objFrm.setVisible(true);
    }

    //method to add action listener to all menu items under a menu
    public void fnAddActionListener(JMenu mnu) {
        if (mnu.getItemCount() != 0) {
            for (int iCount = 0; iCount < mnu.getItemCount(); iCount++) {
                (mnu.getItem(iCount)).addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        fnMenuItemAction(e);
                    }
                });
            }
        }
    }

    //menu item action event
    public void fnMenuItemAction(ActionEvent e) {
        if (e.getSource().equals(mnuItem1)) {
            System.out.println("Menu Item 1");
        } else if (e.getSource().equals(mnuItem2)) {
            System.out.println("Menu Item 2");
        } else if (e.getSource().equals(mnuItem3)) {
            System.out.println("Menu Item 3");
        }
    }

    public static void main(String[] args) {
        new MenuItemEvent().show();
    }
}

或使用以下函数

//fnMenuItemAdd(mnu,mnuItem1)
//etc.

public void fnMenuItemAdd(JMenu mnu, JMenuItem mni) {
    mnu.add(mni);
    mni.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            fnMenuItemAction(e);
        }
    });
}