Home > Back-end >  how to add multiple buttons to a calculator in java
how to add multiple buttons to a calculator in java

Time:10-04

When I run my code it only shows button zero and not button one and button zero is as big as the window. I'm trying to have 9 buttons in the end and after that a few more for buttons like , -, and x. In the end I want it to be a calculator. Thanks for helping. I've already tried making loops. I'm expecting a finished calculator by next month. I think the problem is that the button one is under button zero.

public class hello {
    public static JFrame window;
    public static JPanel panel;
    public static JButton zero;
    public static JButton one;

    public static void main(String[] args) {
        window = new JFrame("idk");
        window.setSize(400, 200);
        window.setLocationRelativeTo(null);
        window.setVisible(true);

        panel = new JPanel();
        panel.setLayout(null);
        
        JLabel label = new JLabel("0");
        label.setSize(399, 35);
        label.setLocation(0, 0);
        label.setBackground(Color.black);
        label.setForeground(Color.white);
        label.setHorizontalAlignment(SwingConstants.RIGHT);
        label.setOpaque(true);
        label.setVisible(true);

        panel.add(label);
        panel.setVisible(true);

        window.add(panel);
        window.setVisible(true);

        zero = new JButton("0");
        zero.setSize(64,64);
        zero.setFont(new Font("Arial", Font.BOLD, 24));
        zero.setFocusPainted(false);
        zero.setLocation(150,299);
        zero.setBackground(Color.black);
        zero.setForeground(Color.orange);
        zero.setVisible(true);
        window.setVisible(true);

        panel.add(zero);
        panel.setVisible(true);

        window.add(zero);
        window.setVisible(true);

        one = new JButton("1");
        one.setSize(64,64);
        one.setFont(new Font("Arial", Font.BOLD, 24));
        one.setFocusPainted(false);
        one.setLocation(150,299);
        one.setBackground(Color.black);
        one.setForeground(Color.orange);
        one.setVisible(true);
        window.setVisible(true);

        panel.add(one);
        panel.setVisible(true);

        window.add(one);
        window.setVisible(true);
    }
}

CodePudding user response:

You don't need to explicitly call setVisible(true) since this is the default for most Components – one exception being JFrame where you do need to explicitly call setVisible(true). However, you should call it only once and only after you have added all the components to it. You should also explicitly call setDefaultCloseOperation.

The default layout manager for [the content pane of] JFrame is BorderLayout and when you add a component to a container using BorderLayout, without a constraint, it gets added to the CENTER and the CENTER takes up as much space as it can. Since you are only adding a single JPanel to the JFrame, it takes up the whole window.

I think the problem is that the button one is under button zero.

Correct, since you give both buttons the exact same size and the exact same location.

I suggest using GridLayout for the calculator buttons.

Next, you need to add ActionListeners to the buttons. Since Java 8, this can be done using method references

Components that you need to manipulate in ActionListeners should usually be [instance] members, i.e. non-static members, of the class.

Below is a sample calculator application. It assumes that the user enters a number, followed by one of the arithmetic operators, followed by another number after which the user presses the = button. It is not production-ready, it is simply intended to help get you started.

(More notes after the code.)

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingConstants;

public class Hello {
    enum Operator {
        ADD("\u002B"), DIVIDE("\u00F7"), MULTIPLY("\u00D7"), SUBTRACT("\u2212");

        private String symbol;

        private Operator(String sign) {
            symbol = sign;
        }

        public String getSymbol() {
            return symbol;
        }
    }

    private static final String BLANK = "                          ";

    private boolean solution;
    private Integer operand1;
    private Integer operand2;
    private JFrame frame;
    private JLabel label;
    private Operator operator;

    private void add(ActionEvent event) {
        operator = Operator.ADD;
        addSymbol();
    }

    private void addSymbol() {
        if (operand1 == null) {
            JOptionPane.showMessageDialog(frame,
                                          "Enter first number.",
                                          "ERROR",
                                          JOptionPane.ERROR_MESSAGE);
        }
        else {
            String text = label.getText()   operator.getSymbol();
            label.setText(text);
        }
    }

    private void buildAndDisplayGui() {
        frame = new JFrame("idk");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(createDisplay(), BorderLayout.PAGE_START);
        frame.add(createButtons(), BorderLayout.CENTER);
        frame.setJMenuBar(createMenuBar());
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    private void clear() {
        solution = false;
        clear2();
        label.setText(BLANK);
    }

    public void clear2() {
        operator = null;
        operand1 = null;
        operand2 = null;
    }

    private JButton createButton(String text, int mnemonic, String tooltip, ActionListener listener) {
        JButton button = new JButton(text);
        if (mnemonic > 0) {
            button.setMnemonic(mnemonic);
        }
        if (tooltip != null) {
            button.setToolTipText(tooltip);
        }
        button.addActionListener(listener);
        button.setFocusPainted(false);
        button.setFont(new Font("Dialog", Font.BOLD, 24));
        button.setBackground(Color.black);
        button.setForeground(Color.orange);
        return button;
    }

    private JPanel createButtons() {
        JPanel buttonsPanel = new JPanel(new GridLayout(0, 4));
        buttonsPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
        buttonsPanel.add(createButton("7", KeyEvent.VK_7, null, this::showOperand));
        buttonsPanel.add(createButton("8", KeyEvent.VK_8, null, this::showOperand));
        buttonsPanel.add(createButton("9", KeyEvent.VK_9, null, this::showOperand));
        buttonsPanel.add(createButton(Operator.DIVIDE.getSymbol(), KeyEvent.VK_SLASH, "Divide", this::divide));
        buttonsPanel.add(createButton("4", KeyEvent.VK_4, null, this::showOperand));
        buttonsPanel.add(createButton("5", KeyEvent.VK_5, null, this::showOperand));
        buttonsPanel.add(createButton("6", KeyEvent.VK_6, null, this::showOperand));
        buttonsPanel.add(createButton(Operator.MULTIPLY.getSymbol(), KeyEvent.VK_X, "Multiply", this::multiply));
        buttonsPanel.add(createButton("1", KeyEvent.VK_4, null, this::showOperand));
        buttonsPanel.add(createButton("2", KeyEvent.VK_5, null, this::showOperand));
        buttonsPanel.add(createButton("3", KeyEvent.VK_6, null, this::showOperand));
        buttonsPanel.add(createButton(Operator.SUBTRACT.getSymbol(), KeyEvent.VK_X, "Subtract", this::subtract));
        buttonsPanel.add(createButton("\u232B", KeyEvent.VK_BACK_SPACE, "Erase", this::erase));
        buttonsPanel.add(createButton("0", KeyEvent.VK_0, null, this::showOperand));
        buttonsPanel.add(createButton("=", KeyEvent.VK_EQUALS, null, this::performCalculation));
        buttonsPanel.add(createButton(Operator.ADD.getSymbol(), KeyEvent.VK_PLUS, "Add", this::add));
        return buttonsPanel;
    }

    private JLabel createDisplay() {
        label = new JLabel(BLANK);
        label.setBackground(Color.black);
        label.setForeground(Color.white);
        label.setFont(new Font("Dialog", Font.BOLD, 24));
        label.setHorizontalAlignment(SwingConstants.TRAILING);
        label.setOpaque(true);
        return label;
    }

    private JMenuBar createMenuBar() {
        JMenuBar menuBar = new JMenuBar();
        JMenu menu = new JMenu("Actions");
        JMenuItem item = new JMenuItem("New");
        item.addActionListener(e -> clear());
        menu.add(item);
        menuBar.add(menu);
        return menuBar;
    }
    
    private void divide(ActionEvent event) {
        operator = Operator.DIVIDE;
        addSymbol();
    }

    private void erase(ActionEvent event) {
        String text = label.getText().trim();
        int len = text.length();
        String newText;
        if (len > 1) {
            newText = text.substring(0, len - 1);
            if (newText.endsWith(" ")) {
                newText = newText.substring(0, newText.length() - 1);
            }
        }
        else {
            newText = BLANK;
        }
        label.setText(newText);
    }

    private void multiply(ActionEvent event) {
        operator = Operator.MULTIPLY;
        addSymbol();
    }

    private void performCalculation(ActionEvent event) {
        Double op1 = Double.valueOf(operand1.doubleValue());
        Double op2 = Double.valueOf(operand2.doubleValue());
        Double result;
        switch (operator) {
            case ADD:
                result = op1   op2;
                break;
            case DIVIDE:
                result = op1 / op2;
                break;
            case MULTIPLY:
                result = op1 * op2;
                break;
            case SUBTRACT:
                result = op1 - op2;
                break;
            default:
                result = null;
                JOptionPane.showMessageDialog(frame,
                                              "Unhandled operator: "   operator,
                                              "WARNING",
                                              JOptionPane.WARNING_MESSAGE);
        }
        if (result != null) {
            label.setText(result.toString());
        }
        solution = true;
        clear2();
    }

    private void showOperand(ActionEvent event) {
        if (solution) {
            label.setText("");
            solution = false;
        }
        String digit = event.getActionCommand();
        String number = label.getText();
        if (number.isBlank()) {
            number = number.trim();
        }
        String text = number   digit;
        if (operator == null) {
            operand1 = Integer.parseInt(text);
        }
        else {
            int ndx = number.indexOf(operator.getSymbol());
            int len = number.length();
            if (len > ndx   1) {
                operand2 = Integer.parseInt(text.substring(ndx   1));
            }
            else {
                operand2 = Integer.parseInt(digit);
            }
        }
        label.setText(text);
    }

    private void subtract(ActionEvent event) {
        operator = Operator.SUBTRACT;
        addSymbol();
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> new Hello().buildAndDisplayGui());
    }
}
  • It is recommended to adhere to Java naming conventions, hence I named the class Hello (rather than hello).
  • I explicitly launch the Event Dispatch Thread (EDT). Although not required, it is recommended.
  • The argument to method invokeLater is a lambda expression
  • I created an enum for the [arithmetic] operators.
  • I used Dialog font since Arial didn't display the [Unicode] erase symbol.
  • The operands are int so they can't be larger than around two billion.
  • Rather than adding more buttons that are usually found on a calculator, I added a menu.
  • Whenever I set the text of label to an empty string, it is not displayed. Hence the use of constant BLANK.

CodePudding user response:

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

public class hello {
    public static JFrame window;
    public static JPanel panel;
    public static JButton zero;
    public static JButton one;

    public static void main(String[] args) {
        window = new JFrame("idk");  
        window.setSize(400, 200);
        //window.setLocationRelativeTo(null);
        //window.setVisible(true);

        panel = new JPanel();
        //panel.setLayout(null);
        
        JLabel label = new JLabel("0");
        label.setSize(399, 35);
        label.setLocation(0, 0);
        label.setBackground(Color.black);
        label.setForeground(Color.white);
        label.setHorizontalAlignment(SwingConstants.RIGHT);
       // label.setOpaque(true);
        //label.setVisible(true);

        panel.add(label);
        //panel.setVisible(true);

        window.add(panel);
        //window.setVisible(true);

  
        zero = new JButton("0");
        zero.setSize(64,64);
        zero.setFont(new Font("Arial", Font.BOLD, 24));
        zero.setFocusPainted(false);
        zero.setLocation(150,299);
        zero.setBackground(Color.black);
        zero.setForeground(Color.orange);
       // zero.setVisible(true);
        //window.setVisible(true);

        panel.add(zero);
       // panel.setVisible(true);

       // window.add(zero);
       // window.setVisible(true);

        one = new JButton("1");
        one.setSize(64,64);
        one.setFont(new Font("Arial", Font.BOLD, 24));
        one.setFocusPainted(false);
        one.setLocation(150,299);
        one.setBackground(Color.black);
        one.setForeground(Color.orange);
        //one.setVisible(true);
        window.setVisible(true);

        panel.add(one);
       // panel.setVisible(true);

        //window.add(one);
        window.setVisible(true);

    }
}

you need to understand the concept of layout managers esp BorderLayout and FlowLayout. Layout managers are responsible for managing the placement of the comnponent on to the containers. BorderLayout is the drfault layout manager of JFrame. if you add multiple components to the JFrame you will see the last component as it will occupy the whole space of the JFrame. FlowLayout is the default layout manager of JPanel.It places the components side by side. One point is that we do not need to set the visiblility of each of the individual components usually , It means when you add components to the container and if the container is visible then the added components will also become visible automatically. Another point is that usually we add components to the container once and the container to the other container if there is such need. so here JPanel instance is the container which are being added to the container Jframe instance

  • Related