简体   繁体   中英

JButtons and JMenuItems not cooperating in ActionListener

Hi all this is my first post!

I'm using this calculator project as tool to teach my self java.

I am generally trying to reproduce Microsoft Windows 7 Calculator program.

So far so good, all the buttons work the way they are supposed to, apart from the more complex button functions in Microsoft Calculator everything is pretty much identical.

Here is my problem, Upon implementing an actionlistener/event for the JMenuBar with the following code

String menuText = ((JMenuItem) evt.getSource()).getText();

    if(menuText.equals("info")){
        System.out.println("it works");
        JOptionPane.showMessageDialog(null, "aha it works");

everything collapses around me!

here is the full code

public class Calculator extends JFrame implements ActionListener {

JButton backSpace, clear, one, two, three, four, five, six, seven, eight,
        nine, zero, period, devision, modulas, subtraction, addition,
        negative, equals;

Font myFont = new Font("ARIAL", Font.BOLD, 40);

JTextArea answerBox = new JTextArea("");

static double numberOne = 0;
static double numberTwo = 0;
static double result;
static String operator = null;

public Calculator() {
    super("Calculator");
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setVisible(true);

    // set up components
    addition = new JButton("+");
    backSpace = new JButton("BACKSPACE");
    clear = new JButton("CLEAR");
    one = new JButton("1");
    two = new JButton("2");
    three = new JButton("3");
    four = new JButton("4");
    five = new JButton("5");
    six = new JButton("6");
    seven = new JButton("7");
    eight = new JButton("8");
    nine = new JButton("9");
    zero = new JButton("0");
    period = new JButton(".");
    devision = new JButton("/");
    modulas = new JButton("*");
    subtraction = new JButton("-");
    negative = new JButton("-N");
    equals = new JButton("=");

    // set up answerbox
    answerBox.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
    answerBox.setFont(myFont);
    answerBox.setEditable(false);

    // set up actionListener
    backSpace.addActionListener(this);
    clear.addActionListener(this);
    one.addActionListener(this);
    two.addActionListener(this);
    three.addActionListener(this);
    four.addActionListener(this);
    five.addActionListener(this);
    six.addActionListener(this);
    seven.addActionListener(this);
    eight.addActionListener(this);
    nine.addActionListener(this);
    zero.addActionListener(this);
    period.addActionListener(this);
    devision.addActionListener(this);
    addition.addActionListener(this);
    modulas.addActionListener(this);
    subtraction.addActionListener(this);
    negative.addActionListener(this);
    equals.addActionListener(this);

    // menu
    JMenuBar menuBar = new JMenuBar();
    JMenu menu = new JMenu("About");
    JMenuItem info = new JMenuItem("Info");

    info.addActionListener(this);
    menu.add(info);
    menuBar.add(menu);
    setJMenuBar(menuBar);

    // set up layout
    GridBagLayout gridBag = new GridBagLayout();
    GridBagConstraints constraints = new GridBagConstraints();
    JPanel pane = new JPanel();
    pane.setLayout(gridBag);

    // default
    constraints.fill = GridBagConstraints.BOTH;
    constraints.anchor = GridBagConstraints.WEST;
    constraints.gridy = 0;
    constraints.gridx = 0;
    constraints.gridwidth = 1;
    constraints.gridheight = 1;
    constraints.weightx = 10;
    constraints.weighty = 10;
    constraints.insets = new Insets(2, 2, 2, 2);

    // answer box
    constraints.gridx = 0;
    constraints.gridy = 0;
    constraints.gridwidth = 6;
    answerBox.append("0");

    gridBag.setConstraints(answerBox, constraints);
    pane.add(answerBox);

    // backSPace
    constraints.gridx = 0;
    constraints.gridy = 1;
    constraints.gridwidth = 3;

    gridBag.setConstraints(backSpace, constraints);
    pane.add(backSpace);

    // clear

    constraints.anchor = GridBagConstraints.EAST;
    constraints.gridx = 3;
    constraints.gridy = 1;
    constraints.weightx = 10;
    gridBag.setConstraints(clear, constraints);
    pane.add(clear);

    // nine
    constraints.gridwidth = 1;
    constraints.weightx = 1;
    constraints.gridx = 0;
    constraints.gridy = 3;
    gridBag.setConstraints(nine, constraints);
    pane.add(nine);

    // eight
    constraints.gridx = 1;
    constraints.gridy = 3;
    gridBag.setConstraints(eight, constraints);
    pane.add(eight);

    // seven
    constraints.gridx = 2;
    constraints.gridy = 3;
    gridBag.setConstraints(seven, constraints);
    pane.add(seven);

    // devision
    constraints.gridwidth = 1;
    constraints.weightx = 1;
    constraints.gridx = 3;
    constraints.gridy = 3;
    constraints.anchor = GridBagConstraints.SOUTH;
    gridBag.setConstraints(devision, constraints);
    pane.add(devision);

    // EQUALS
    constraints.gridx = 4;
    constraints.gridy = 3;
    constraints.gridwidth = 2;
    constraints.gridheight = 4;
    constraints.weighty = 30;
    constraints.anchor = GridBagConstraints.SOUTH;
    gridBag.setConstraints(equals, constraints);
    pane.add(equals);

    // six
    constraints.weighty = 10;
    constraints.gridwidth = 1;
    constraints.gridheight = 1;
    constraints.gridx = 0;
    constraints.gridy = 4;
    gridBag.setConstraints(six, constraints);
    pane.add(six);

    // five
    constraints.gridx = 1;
    constraints.gridy = 4;
    gridBag.setConstraints(five, constraints);
    pane.add(five);

    // four
    constraints.gridwidth = 1;

    constraints.gridx = 2;
    constraints.gridy = 4;
    gridBag.setConstraints(four, constraints);
    pane.add(four);

    // Addition
    constraints.gridwidth = 1;
    constraints.weightx = 1;
    constraints.gridx = 3;
    constraints.gridy = 4;
    gridBag.setConstraints(addition, constraints);
    pane.add(addition);

    // three
    constraints.gridx = 0;
    constraints.gridy = 5;
    gridBag.setConstraints(three, constraints);
    pane.add(three);

    // two
    constraints.gridx = 1;
    constraints.gridy = 5;
    gridBag.setConstraints(two, constraints);
    pane.add(two);

    // one
    constraints.gridx = 2;
    constraints.gridy = 5;
    gridBag.setConstraints(one, constraints);
    pane.add(one);

    // subtraction
    constraints.gridx = 3;
    constraints.gridy = 5;
    gridBag.setConstraints(subtraction, constraints);
    pane.add(subtraction);

    // zero
    constraints.gridx = 0;
    constraints.gridy = 6;
    constraints.gridwidth = 2;
    gridBag.setConstraints(zero, constraints);
    pane.add(zero);

    // period
    constraints.gridx = 2;
    constraints.gridy = 6;
    constraints.gridwidth = 1;
    gridBag.setConstraints(period, constraints);
    pane.add(period);

    // multiplication
    constraints.gridx = 3;
    constraints.gridy = 6;
    constraints.gridwidth = 1;
    gridBag.setConstraints(modulas, constraints);
    pane.add(modulas);

    pack();
    add(pane);

}

public static void main(String[] args) {
    Calculator frame = new Calculator();
    frame.setSize(300, 350);
}

public void actionPerformed(ActionEvent evt){       
    Object source = evt.getSource();
    String menuText = ((JMenuItem) evt.getSource()).getText();

    if(menuText.equals("info")){
        System.out.println("it works");
        JOptionPane.showMessageDialog(null, "aha it works");
    }

    else if(source == one){
        answerBox.append("1");


    }else if (source == two){
        answerBox.append("2");
    }

    else if (source == three){
        answerBox.append("3");
    }

    else if (source == four){
        answerBox.append("4");
    }

    else if (source == five){
        answerBox.append("5");
    }

    else if (source == six){
        answerBox.append("6");
    }

    else if (source == seven){
        answerBox.append("7");
    }

    else if (source == eight){
        answerBox.append("8");
    }

    else if (source == nine){
        answerBox.append("9");
    }

    else if (source == zero){
        answerBox.append("0");
    }

    else if (source == addition){
        numberOne=Double.parseDouble(answerBox.getText());
        operator="+";
        answerBox.setText("");
    }   

    else if (source == subtraction){
        numberOne=Double.parseDouble(answerBox.getText());
        operator="-";
        answerBox.setText("");
        }

    else if (source == modulas){
        numberOne=Double.parseDouble(answerBox.getText());
        operator="*";
        answerBox.setText("");

    }
    else if (source == devision){
        numberOne=Double.parseDouble(answerBox.getText());
        operator="/";
        answerBox.setText("");

    }
    else if (source == period){
        answerBox.append(".");
    }

    else if(source == equals){

           numberTwo=Double.parseDouble(answerBox.getText());
           if(operator.equals("+"))
               result=numberOne+numberTwo;
           else if(operator.equals("-"))
               result=numberOne-numberTwo;
           else if(operator.equals("*"))
               result=numberOne-numberTwo;
           else if(operator.equals("/"))
               result=numberOne/numberTwo;

           answerBox.setText(" "+result);
           operator="=";

    }

    else if(source == clear){       
        numberOne=0;
        numberTwo=0;
        answerBox.setText("");
    }


}


}
String menuText = ((JMenuItem) evt.getSource()).getText();

I'm guessing you are getting a ClassCastException on the above statement.

That code assumes the event is generated by a JMenuItem. The problem is that you are using the same ActionListener for you JButtons and your JMenuItems so you can't assume the source object is a JMenuItem.

It is not a good idea to implement all your code in a single ActionListener. You can share an ActionListener for like functions. For example in the following code the pressing of the digit buttons is always the same so you can use the same listener:

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

public class ButtonCalculator extends JPanel
{
    private JButton[] buttons;
    private JTextField display;

    public ButtonCalculator()
    {
        Action numberAction = new AbstractAction()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                display.replaceSelection(e.getActionCommand());
            }
        };

        display = new JTextField();
        display.setEditable( false );
        display.setHorizontalAlignment(JTextField.RIGHT);

        JPanel buttonPanel = new JPanel();
        buttonPanel.setLayout( new GridLayout(0, 5) );
        buttons = new JButton[10];

        for (int i = 0; i < buttons.length; i++)
        {
            String text = String.valueOf(i);
            JButton button = new JButton( text );
            button.addActionListener( numberAction );
            buttons[i] = button;
            buttonPanel.add( button );

            //  Support Key Bindings

            KeyStroke pressed = KeyStroke.getKeyStroke(text);
            InputMap inputMap = button.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
            inputMap.put(pressed, text);
            button.getActionMap().put(text, numberAction);
        }

        setLayout( new BorderLayout() );
        add(display, BorderLayout.NORTH);
        add(buttonPanel, BorderLayout.SOUTH);
    }

    private static void createAndShowUI()
    {
        UIManager.put("Button.margin", new Insets(5, 10, 5, 10) );
        JFrame frame = new JFrame("Button Calculator");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add( new ButtonCalculator() );
        frame.setResizable( false );
        frame.pack();
        frame.setLocationByPlatform( true );
        frame.setVisible( true );
    }

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

For your other Actions ("+" , "-" ...) you should create separate listeners.

Before you cast evt.getSource to JMenuItem you have to check of source is a JMenuItem. Change your method actionPerformed in the beginning like my example and it works (You have to ask for 'Info' not for 'info'). +1 for camickr - different actionListener is the way for better code quality.

@Override
public void actionPerformed(ActionEvent evt) {
    Object source = evt.getSource();

    if (source.getClass() == JMenuItem.class) {
        String menuText = ((JMenuItem) evt.getSource()).getText();

        if (menuText.equals("info")) {
            System.out.println("it works");
            JOptionPane.showMessageDialog(null, "aha it works");
        }
    }
    else if (source == one) {
        answerBox.append("1");
    }

Several things jump out at me...

You can't rely on the source type being a given instance of a class...

Object source = evt.getSource();
String menuText = ((JMenuItem) evt.getSource()).getText();

This is likely to cause you a ClassCastException

Also, Info != info

You define your menu item as ....

JMenuItem info = new JMenuItem("Info");

But you test it's text content with...

if(menuText.equals("info")){

String comparison in Java is case sensitive (unless you use equalsIgnoresCase )

You should be supply and using the actionCommand properties.

For example...

JMenuItem info = new JMenuItem("Info");
info.setActionComand("infoMenu");

Then in you actionPeformed method you could do something like...

if("infoMenu".equals(evt.getActionCommand())){...}

I would also suggest you take a look at the How to use Actions , these are very powerful, isolated actions, which can be applied to multiple different parts of the application, including menus, buttons and the key bindings API

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM