Java 如何为多个JMenuItems创建ActionListener?

Java 如何为多个JMenuItems创建ActionListener?,java,swing,actionlistener,anonymous-class,jmenuitem,Java,Swing,Actionlistener,Anonymous Class,Jmenuitem,我在使用actionListener的匿名内部类时遇到困难。有人能解释一下我的代码有什么问题,以及如何将匿名内部类与actionListener一起使用吗。我试图在一个类中创建菜单栏,在另一个类中创建动作侦听器。我在尝试使用匿名内部类时遇到了一些困难。java网站不清楚。你能给我解释一下并帮我修改代码吗 public class Listener implements ActionListener { HangmanView hangmanView = new HangmanV

我在使用actionListener的匿名内部类时遇到困难。有人能解释一下我的代码有什么问题,以及如何将匿名内部类与actionListener一起使用吗。我试图在一个类中创建菜单栏,在另一个类中创建动作侦听器。我在尝试使用匿名内部类时遇到了一些困难。java网站不清楚。你能给我解释一下并帮我修改代码吗

 public class Listener implements ActionListener {
        HangmanView hangmanView = new HangmanView();
        JFrame dialogFrame = new JFrame();
        ImageIcon logo = new ImageIcon("logo.png");

        public void listener1() {
            hangmanView.getMenuItem().addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {// right click key
                    JOptionPane.showMessageDialog(dialogFrame, "Developer: Joe"
                            , "Developer",
                            JOptionPane.INFORMATION_MESSAGE, logo);
                }// end actionPerformed method
            });
        }
    }
另一类:

public class HangmanView {

    public JMenuItem getMenuItem() {
        JMenuItem menuItem = new JMenuItem("Developer", KeyEvent.VK_T);
        menuItem.addActionListener(new Listener());
        return menuItem;
    }

    public JMenuBar menuBar() {

        JMenuBar menuBar = new JMenuBar();
        JMenu menu = new JMenu("File");
        menuBar.add(menu);
        menu.add(getMenuItem());// return here
        return menuBar;
    }

Listener
,通过其继承层次结构成为
ActionListener

public class Listener implements ActionListener {
需要实现
actionperformed(ActionEvent)
方法

@Override
public void actionPerformed(ActionEvent e) {
    // implement it         
}

但是,由于您似乎要添加一个匿名的
ActionListener
,所以不要让您的
Listener
类实现
ActionListener
。删除该位。

Listener
,通过继承层次结构作为
ActionListener

public class Listener implements ActionListener {
需要实现
actionperformed(ActionEvent)
方法

@Override
public void actionPerformed(ActionEvent e) {
    // implement it         
}

但是,由于您似乎要添加一个匿名的
ActionListener
,所以不要让您的
Listener
类实现
ActionListener
。删除该位。

Listener
,通过继承层次结构作为
ActionListener

public class Listener implements ActionListener {
需要实现
actionperformed(ActionEvent)
方法

@Override
public void actionPerformed(ActionEvent e) {
    // implement it         
}

但是,由于您似乎要添加一个匿名的
ActionListener
,所以不要让您的
Listener
类实现
ActionListener
。删除该位。

Listener
,通过继承层次结构作为
ActionListener

public class Listener implements ActionListener {
需要实现
actionperformed(ActionEvent)
方法

@Override
public void actionPerformed(ActionEvent e) {
    // implement it         
}

但是,由于您似乎要添加一个匿名的
ActionListener
,所以不要让您的
Listener
类实现
ActionListener
。删除该位。

如果您试图为不同的
JMenuItem
s实现侦听器,那么我要做的是创建一个自定义的
Action
类,您可以将它用于多个
JMenuItem
s,因为
JMenuItem
s是何时使用
操作的一个很好的例子

private class MyAction extends AbstractAction {

    String name;

    public MyAction(String name, Icon icon) {
        super(name, icon);
        this.name = name;
    }

    public MyAction(String name, Icon icon, String desc,
            Integer mnemonic, KeyStroke accelorator) {
        super(name, icon);
        putValue(Action.SHORT_DESCRIPTION, desc);
        putValue(Action.MNEMONIC_KEY, mnemonic);
        putValue(Action.ACCELERATOR_KEY, accelorator);
        this.name = name;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        switch (name) {
            case "menu1Action":
                // do something for menuItem1
                break;
            case "menu2Action":
                // do something for menuItem2
                break;
            case "menu3Action":
                // do something for menuItem3
                break;
        }
    }
}
将此类作为
HangmanView
的内部类。然后,您可以为每个
JMenuItem
创建此自定义
Action
类的实例。这里有一个例子

Action menu1Action = new MyAction(
 /* arg 1 */    "menu1Action", 
 /* arg 2 */    someIcon,
 /* arg 3 */    "Some Short description of the action",
 /* arg 4 */    new Integer(KeyEvent.VK_T),
 /* arg 5 */    KeyStroke.getKeyStroke(KeyEvent.VK_T, ActionEvent.CTRL_MASK));
  • 第一个参数是操作的名称。此名称将是您将在菜单中看到的名称
  • 第二个参数是您将在名称旁边的菜单中看到的图标
  • 第三个参数是菜单项操作的描述
  • 第四个参数是助记符(即Alt+T)
  • 第五个参数是加速器(即Ctrl+T)
当您向
JMenu
添加
操作时,该
操作的标题将自动放置为您在
JMenu
中看到的标题。因此,您只需将此自定义
操作添加到
JMenu
。您根本不需要实际创建
JMenuItem
操作
将替代
JMenuItem
。只需将所有
MyAction
对象添加到
JMenu

menu.add(menu1Action);
我遗漏的是
actionPerformed
中每个单独的
开关案例的实现。
案例
将是您在构造函数中命名的
操作
。因为我将
操作命名为“menu1Action”,所以在开关的大小写中应该有相应的名称。在这种情况下,您可以执行您的
JOptionPane
,或者在单击或通过键盘访问
JMenuItem
时希望执行的任何其他操作

使用
操作
的另一大好处是它可以服务于多种用途。使用您创建的相同的
MyAction menu1Action
,您可以对
JToolBar
使用相同的
Action
。无需对上述
菜单1操作进行任何更改,您只需执行以下操作:

JTooBar toolbar = new JToolBar();
toolbar.add(menu1Action);
现在,在工具栏和菜单项中,您可以执行相同的操作。工具栏将仅显示图标,而不显示名称

这里有一个例子。我要做的是创建三个不同的
MyAction
对象。一个用于左对齐,一个用于中心对齐,一个用于右对齐。这些操作中的每一个都会对三个单独的组件(一个菜单项、一个收费条和一个按钮)分别使用三次

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

public class ActionInterfaceDemo extends JFrame {
    static JPanel buttonPanel = new JPanel();
    static FlowLayout flowLayout = new FlowLayout();

    public ActionInterfaceDemo(){


        ImageIcon centerIcon = new ImageIcon(
                ActionInterfaceDemo.class.getResource("image/centeralignment.png"));
        ImageIcon rightIcon = new ImageIcon(
                ActionInterfaceDemo.class.getResource("image/rightalignment.png"));
        ImageIcon leftIcon = new ImageIcon(
                ActionInterfaceDemo.class.getResource("image/leftalignment.png"));

        Action leftAction = new MyAction("Left", leftIcon,
                "Left alignment for the buttons in the panel",
                new Integer(KeyEvent.VK_L),
                KeyStroke.getKeyStroke(KeyEvent.VK_L, ActionEvent.CTRL_MASK));
        Action rightAction = new MyAction("Right", rightIcon,
                "Right alignment for the buttons in the panel",
                new Integer(KeyEvent.VK_R),
                KeyStroke.getKeyStroke(KeyEvent.VK_R, ActionEvent.CTRL_MASK));
        Action centerAction = new MyAction("Center", centerIcon,
                "Center alignment for the buttons in the panel",
                new Integer(KeyEvent.VK_C),
                KeyStroke.getKeyStroke(KeyEvent.VK_C, ActionEvent.CTRL_MASK));

        JMenuBar menuBar = new JMenuBar();
        JMenu menuAlignment = new JMenu("Alignment");
        setJMenuBar(menuBar);
        menuBar.add(menuAlignment);

        menuAlignment.add(leftAction);
        menuAlignment.add(centerAction);
        menuAlignment.add(rightAction);

        JToolBar toolBar = new JToolBar("Alignment");
        toolBar.setBorder(BorderFactory.createLineBorder(Color.BLUE));
        toolBar.add(leftAction);
        toolBar.add(centerAction);
        toolBar.add(rightAction);

        buttonPanel.setLayout(flowLayout);
        JButton jbtLeft = new JButton(leftAction);
        JButton jbtCenter = new JButton(centerAction);
        JButton jbtRight = new JButton(rightAction);
        buttonPanel.add(jbtLeft);
        buttonPanel.add(jbtCenter);
        buttonPanel.add(jbtRight);

        add(toolBar, BorderLayout.EAST);
        add(buttonPanel, BorderLayout.CENTER);

        pack();
        setLocationRelativeTo(null);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable(){
            public void run(){
                new ActionInterfaceDemo();
            }
        });

    }

    private class MyAction extends AbstractAction {

        String name;

        public MyAction(String name, Icon icon, String desc,
                Integer mnemonic, KeyStroke accelorator) {
            super(name, icon);
            putValue(Action.SHORT_DESCRIPTION, desc);
            putValue(Action.MNEMONIC_KEY, mnemonic);
            putValue(Action.ACCELERATOR_KEY, accelorator);
            this.name = name;
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            switch (name) {
                case "Left":
                    flowLayout.setAlignment(FlowLayout.LEFT);
                    break;
                case "Right":
                    flowLayout.setAlignment(FlowLayout.RIGHT);
                    break;
                case "Center":
                    flowLayout.setAlignment(FlowLayout.CENTER);
                    break;
            }
            buttonPanel.revalidate();
        }
    }
}

您可以按菜单、工具栏或按钮中的“左”键,它们将产生相同的结果,因为它们来自相同的
操作

如果你想测试的话,这里是我使用的图片

注意您不必使用这两个确切的构造函数中的任何一个。您可以使用不同的参数创建自己的参数。这只是我喜欢使用的一个定制的


另请参见

如果您试图为不同的
JMenuItem
s实现侦听器,我要做的是创建一个自定义的
Action
类,您可以将其用于多个
JMenuItem
s,因为
JMenuItem
是何时使用
操作的一个很好的示例

private class MyAction extends AbstractAction {

    String name;

    public MyAction(String name, Icon icon) {
        super(name, icon);
        this.name = name;
    }

    public MyAction(String name, Icon icon, String desc,
            Integer mnemonic, KeyStroke accelorator) {
        super(name, icon);
        putValue(Action.SHORT_DESCRIPTION, desc);
        putValue(Action.MNEMONIC_KEY, mnemonic);
        putValue(Action.ACCELERATOR_KEY, accelorator);
        this.name = name;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        switch (name) {
            case "menu1Action":
                // do something for menuItem1
                break;
            case "menu2Action":
                // do something for menuItem2
                break;
            case "menu3Action":
                // do something for menuItem3
                break;
        }
    }
}
将此类作为
HangmanView
的内部类。然后,您可以为每个
JMenuItem
创建此自定义
Action
类的实例。这里有一个例子

Action menu1Action = new MyAction(
 /* arg 1 */    "menu1Action", 
 /* arg 2 */    someIcon,
 /* arg 3 */    "Some Short description of the action",
 /* arg 4 */    new Integer(KeyEvent.VK_T),
 /* arg 5 */    KeyStroke.getKeyStroke(KeyEvent.VK_T, ActionEvent.CTRL_MASK));
  • 第一个参数是操作的名称。此名称将是您将在菜单中看到的名称
  • 第二个参数是您将在名称旁边的菜单中看到的图标
  • 第三个参数是菜单项操作的描述
  • 第四个参数是助记符(即Alt+T)
  • 第五个参数是加速器(即Ctrl+T)