0
package javaapplication2;

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



public class Calc extends JFrame implements ActionListener {

private JButton b1, b2, b3, b4,b5,b6,b7,b8,b9,b0;
JButton[] label = {b1, b2, b3, b4, b5,b6,b7,b8,b9,b0};
String[] numKeys = {"1","2","3","4","5","6","7","8","9","0"};
JPanel numPad;
JPanel opPad;
JTextField displayPanel;

 public Calc() {
 super("Calculator");
 setSize(250,200);
    setDefaultCloseOperation(EXIT_ON_CLOSE);    
    setVisible(true);

    displayPanel = new JTextField(20);
    numPad = new JPanel();
    numPad.setLayout(new GridLayout(4, 3));  
    opPad = new JPanel();
    opPad.setLayout(new GridLayout(4, 1));
    getContentPane().setLayout(new BorderLayout());
    getContentPane().add(numPad,BorderLayout.LINE_START);
    getContentPane().add(displayPanel, BorderLayout.PAGE_START);

    for (int i = 0; i <label.length;i++) {
        label[i] = new JButton(numKeys[i]);
        numPad.add(label[i]);
        label[i].addActionListener(this);


    }


    b2.addActionListener(this);

 }
 public void actionPerformed(ActionEvent a) {
    if (a.getSource() == b1)                     
            displayPanel.setText("1");
}


    public static void main(String args[]) {
Calc c = new Calc();






}
}

Hi, I've attempted to add numbered Jbuttons and add the action listener within a single loop in my attempt to make a calculator, The buttons are created and added to the panel however pressing "1" has no effect when it should display a 1 on the text field

5 Answers 5

2
private JButton b1, b2, b3, b4,b5,b6,b7,b8,b9,b0;
JButton[] label = {b1, b2, b3, b4, b5,b6,b7,b8,b9,b0};

b1-b0 are null by default. In this code:

for (int i = 0; i <label.length;i++) {
    label[i] = new JButton(numKeys[i]);
    numPad.add(label[i]);
    label[i].addActionListener(this);
}

you assign the buttons to the label array, but not to the variables b1-b0. Therefore you are actually checking for == null here

if (a.getSource() == b1)

The solution: remove those b1-b0 variables (you got the array anyway) and check like this:

if (a.getSource() == label[0])
Sign up to request clarification or add additional context in comments.

1 Comment

Don't use an ActionListener with nested if statements to determine which button was clicks. Instead write a generic Action. I provided an example.
0

First you initialize the buttons to null and fill the label array with those null references.

During the loop, you create new objects and replace them in the label array. The original references are still pointing to null.

In the action event you compare source = the new buttons with the old references which are pointing to null. This is fault.

Just initialize the buttons before you add them to the label array, and don't create new buttons in your loop. Fixed!

Comments

0

I would recommend using actioncommand in for loop and then checking the same in action listener, label[i].setActionCommand(numKeys[i]); and then in action listener something like this if (a.getActionCommand().equals("1"))

Check out this SO question, Java Button Action Command, it explains usage of ActionCommand

Hope this helps !!!

Comments

0

I do not think it a good idea to store buttons in array but if you do still want it is better to use Arrais.asList ()

    import java.awt.*;
    import java.awt.event.*;
    import java.util.Arrays;
    import java.util.Collection;
    import javax.swing.*;

    class Calc extends JFrame {
      Collection<JButton> buttons = Arrays.asList(
        new JButton("1"),
        new JButton("2"),
        new JButton("3"),
        new JButton("4"),
        new JButton("5"),
        new JButton("6"),
        new JButton("7"),
        new JButton("8"),
        new JButton("9"),
        new JButton("0"));
      JPanel numPad;
      JPanel opPad;
      JTextField displayPanel;

      public Calc() {
        super("Calculator");
        setSize(250, 200);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setVisible(true);    

        displayPanel = new JTextField(20);
        numPad = new JPanel();
        numPad.setLayout(new GridLayout(4, 3));
        opPad = new JPanel();
        opPad.setLayout(new GridLayout(4, 1));
        getContentPane().setLayout(new BorderLayout());
        getContentPane().add(numPad, BorderLayout.LINE_START);
        getContentPane().add(displayPanel, BorderLayout.PAGE_START);    

        for (final JButton button : buttons) {
          button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
              displayPanel.setText(displayPanel.getText() + button.getText());
            }
          });
          numPad.add(button);
        }
      }

  public static void main(String args[]) {
    Calc c = new Calc();
  }
}

3 Comments

"I do not think it a good idea to store buttons in array" - Why? If you only have a fixed number of elements, arrays are generally simpler (IMHO)
Yes of course but I'm not sure that there really need access by index since it is sufficient iterate over a collection in order to register listeners. Sorry for my bad english.
And in order to keep fixed number of elements in the collection, I usually use Collections.unmodifiableList because UnmodifiableList limits not only the addition but also replacement of elements Collection.
0

Write a generic Action so you don't have to use nested if statements:

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

public class CalculatorPanel extends JPanel
{
    private JTextField display;

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

        setLayout( new BorderLayout() );

        display = new JTextField();
        display.setEditable( false );
        display.setHorizontalAlignment(JTextField.RIGHT);
        add(display, BorderLayout.NORTH);

        JPanel buttonPanel = new JPanel();
        buttonPanel.setLayout( new GridLayout(0, 5) );
        add(buttonPanel, BorderLayout.CENTER);

        for (int i = 0; i < 10; i++)
        {
            String text = String.valueOf(i);
            JButton button = new JButton( text );
            button.addActionListener( numberAction );
            button.setBorder( new LineBorder(Color.BLACK) );
            button.setPreferredSize( new Dimension(50, 50) );
            buttonPanel.add( button );

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

    private static void createAndShowUI()
    {
//      UIManager.put("Button.margin", new Insets(10, 10, 10, 10) );

        JFrame frame = new JFrame("Calculator Panel");
        frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        frame.add( new CalculatorPanel() );
        frame.pack();
        frame.setLocationRelativeTo( null );
        frame.setVisible(true);
    }

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

This example also uses Key Bindings, so you can press "1" on the keyboard or click the "1" button.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.