如何为多个JMenuItem创建ActionListener?

时间:2013-12-29 00:40:50

标签: java swing actionlistener anonymous-class jmenuitem

我在使用带有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;
    }

4 个答案:

答案 0 :(得分:3)

如果您正在尝试为不同的JMenuItem实现侦听器,那么我要做的是创建一个可用于多个Action的自定义JMenuItem类,如JMenuItem是何时使用Action的一个很好的例子。

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的内部类。然后,您可以为每个Action创建此自定义JMenuItem类的实例。这是一个例子

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 )。

当您向Action添加JMenu时,Action的标题将自动按照您在JMenu中的显示放置。因此,您只需将此自定义Action添加到JMenu即可。您根本不必实际创建JMenuItemAction将替代JMenuItem。只需将所有MyAction个对象添加到JMenu

menu.add(menu1Action);

我遗漏的是switch case中每个单独actionPerformed的实施。 case将是您在构造函数中命名action的内容。因为我将Action命名为“menu1Action”,所以我应该在switch case中有相应的名称。在这种情况下,当您点击或通过键盘访问JOptionPane时,您可以执行JMenuItem或其他您希望执行的操作。

使用Action的另一个好处是它可以用于多种用途。使用您创建的相同MyAction menu1Action,您可以对Action使用相同的JToolBar。如果不对上述menu1Action进行任何更改,您可以这样做:

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();
        }
    }
}

enter image description here

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

以下是我想要测试的图像

enter image description here enter image description here enter image description here

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

Aslo见 How to use Action tutorial

答案 1 :(得分:0)

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

public class Listener implements ActionListener {

需要实现actionPerfomed(ActionEvent)方法

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

但是,由于您似乎要添加匿名ActionListener,因此请不要使用Listener类实现ActionListener。删除那一点。

答案 2 :(得分:0)

您的面向对象编程已遍布各处。您在OP中的代码看起来应该是某种GUI,不同的类以某种方式协同工作,但它只是在整个地方创建新对象。它有太多原因无效。我建议你坚持一些简单的事情,直到你更好地掌握这一切是如何运作的。

在你的另一个问题中,你也有一个非常好的建议,就像这个很多,但你并没有真正遵循它。你的代码完全不同。

这是一个非常基本的GUI。你有一个对象,其中包含所有字段。一切都在一个地方。包含对象是侦听器,并根据事件源决定要执行的操作。你应该坚持使用这样的设计,直到你对OOP更加熟悉。

public class HangmanView
implements ActionListener {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new HangmanView().setFrameVisible(true);
            }
        });
    }

    private JFrame theFrame = new JFrame("Main Window");
    private JPanel theContent = new JPanel();

    private JMenuBar theBar = new JMenuBar();
    private JMenu fileMenu = new JMenu("File");
    private JMenuItem exitMenuItem = new JMenuItem("Exit");
    private JMenuItem devMenuItem = new JMenuItem("Developer");

    public HangmanView() {
        assert SwingUtilities.isEventDispatchThread();

        exitMenuItem.addActionListener(this);
        devMenuItem.addActionListener(this);

        fileMenu.add(exitMenuItem);
        theBar.add(fileMenu);
        theBar.add(devMenuItem);

        theContent.setPreferredSize(new Dimension(500, 500));

        theFrame.setJMenuBar(theBar);
        theFrame.setContentPane(theContent);
        theFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        theFrame.pack();
        theFrame.setLocationRelativeTo(null);
    }

    public void setFrameVisible(boolean vis) {
        theFrame.setVisible(vis);
    }

    @Override
    public void actionPerformed(ActionEvent ae) {
        if(ae.getSource() == devMenuItem) {
            showDevDiag();
        } else if(ae.getSource() == exitMenuItem) {
            systemExit();
        }
    }

    private void showDevDiag() {
        JOptionPane.showMessageDialog(
            theFrame,
            "Developer: Joe",
            "Developer",
            JOptionPane.INFORMATION_MESSAGE,
            null
        );
    }

    private void systemExit() {
        System.exit(0);
    }
}

答案 3 :(得分:0)

如果我应该使用匿名类,那应该做什么:

public static void main(String args[]){
    /*bla bla bla...*/
    JButton button1=new JButton("button1");
    button1.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent ae){
            /*bla bla bla...*/
        }
    };
}

另一方面,我总是这样做:

public class Class implements Runnable,ActionListener
{
    private static Map<Thread,ActionEvent> THREAD_ATTRIB
    =new HashMap<Thread,ActionEvent> (0);

    JButton button1=new JButton("button1");
    JButton button2=new JButton("button2");
    //constructor
    public Class(){
        this.button1.addActionListener(this);
        this.button2.addActionListener(this);
    }

    @Override
    public void actionPerformed(ActionEvent ae){
        Thread thread=new Thread(this);
        THREAD_ATTRIB.put(thread,ae);
        thread.start();
    }

    @Override
    public void run(){
        ActionEvent ae=THREAD_ATTRIB.get(Thread.currentThread());
        if(ae!=null){
            Object source=ae.getSource();
            if(source.equals(this.button1){
                /*bla bla bla...*/
            } else if(source.equals(this.button2){
                /*bla bla bla...*/
            }
        } else{
            /*bla bla bla...*/
        }
    }
}