Create Simple Calculator using Java Swing

Introduction

The Simple Calculator is a GUI-based Java application developed using the Swing library. It performs basic arithmetic operations such as addition, subtraction, multiplication, and division. The user inputs two numbers, selects an operation, and the result is displayed in the result field.

Project Objectives

  • Build a user-friendly interface for a basic calculator using Java Swing.
  • Enable arithmetic operations such as Addition, Subtraction, Multiplication, and Division.
  • Display error messages for invalid inputs or divide-by-zero operations.
  • Provide a clear/reset feature to reset the input fields and result.

Features

  • Graphical User Interface (GUI): Uses Java Swing components such as JTextField, JButton, JLabel, JPanel.
  • Basic Operations: Supports addition, subtraction, multiplication, and division.
  • Error Handling: Handles invalid inputs and division by zero.
  • Reset Button: Clears all input fields and the result display.
  • Responsive Design: Components are well-aligned with appropriate padding and spacing.

Tools and Technologies Used

  • Programming Language: Java
  • GUI Library: Java Swing
  • Development Environment: Any IDE (e.g., IntelliJ IDEA, Eclipse, NetBeans) or Java compiler (JDK).

Prerequisites

  • Java Development Kit (JDK) installed.
  • Basic knowledge of Java programming and Swing components.

Project Structure

  1. The application consists of a single Java class, Calculator.java, which contains:

    1. Main Frame Setup: Configures the main window of the application.
    2. Input Fields: Two text fields for entering numbers.
    3. Result Display: A non-editable text field to show the result.
    4. Buttons: Operation buttons (Add, Subtract, Multiply, Divide) and a Clear button.
    5. Action Listeners: To handle button clicks and perform operations.

Code

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

public class Calculator {
    private JTextField num1Field, num2Field, resultField;
    private JButton addButton, subtractButton, multiplyButton, divideButton, clearButton;

    public Calculator() {
        // Set up the frame
        JFrame frame = new JFrame("Simple Calculator");
        frame.setSize(400, 300);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new BorderLayout());

        // Heading at the top
        JLabel headingLabel = new JLabel("edSlash Coding Hub Calculator", JLabel.CENTER);
        headingLabel.setFont(new Font("Arial", Font.BOLD, 22));
        headingLabel.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0));
        frame.add(headingLabel, BorderLayout.NORTH);

        // Create the form panel
        JPanel formPanel = new JPanel(new GridLayout(5, 2, 10, 10));
        formPanel.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));

        // Number 1 Input
        JLabel num1Label = new JLabel("Number 1:");
        num1Field = new JTextField();
        formPanel.add(num1Label);
        formPanel.add(num1Field);

        // Number 2 Input
        JLabel num2Label = new JLabel("Number 2:");
        num2Field = new JTextField();
        formPanel.add(num2Label);
        formPanel.add(num2Field);

        // Result Display
        JLabel resultLabel = new JLabel("Result:");
        resultField = new JTextField();
        resultField.setEditable(false); // Result field is read-only
        formPanel.add(resultLabel);
        formPanel.add(resultField);

        // Operation Buttons
        addButton = new JButton("Add");
        subtractButton = new JButton("Subtract");
        multiplyButton = new JButton("Multiply");
        divideButton = new JButton("Divide");
        clearButton = new JButton("Clear");

        JPanel buttonPanel = new JPanel(new GridLayout(1, 5, 5, 5));
        buttonPanel.add(addButton);
        buttonPanel.add(subtractButton);
        buttonPanel.add(multiplyButton);
        buttonPanel.add(divideButton);
        buttonPanel.add(clearButton);

        // Add components to the frame
        frame.add(formPanel, BorderLayout.CENTER);
        frame.add(buttonPanel, BorderLayout.SOUTH);

        // Add Action Listeners using Lambdas
        ActionListener listener = e -> handleOperation(e.getActionCommand());
        addButton.addActionListener(listener);
        subtractButton.addActionListener(listener);
        multiplyButton.addActionListener(listener);
        divideButton.addActionListener(listener);
        clearButton.addActionListener(e -> clearFields());

        // Make the frame visible
        frame.setVisible(true);
    }

    private void handleOperation(String operation) {
        try {
            double num1 = Double.parseDouble(num1Field.getText().trim());
            double num2 = Double.parseDouble(num2Field.getText().trim());
            double result = 0;

            switch (operation) {
                case "Add" -> result = num1 + num2;
                case "Subtract" -> result = num1 - num2;
                case "Multiply" -> result = num1 * num2;
                case "Divide" -> {
                    if (num2 == 0) {
                        showError("Cannot divide by zero.");
                        return;
                    }
                    result = num1 / num2;
                }
            }

            resultField.setText(String.valueOf(result));
        } catch (NumberFormatException ex) {
            showError("Please enter valid numbers.");
        }
    }

    private void showError(String message) {
        JOptionPane.showMessageDialog(null, message, "Input Error", JOptionPane.ERROR_MESSAGE);
    }

    private void clearFields() {
        num1Field.setText("");
        num2Field.setText("");
        resultField.setText("");
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(Calculator::new);
    }
}

				
			

Code

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

public class Calculator {
    private JTextField num1Field, num2Field, resultField;
    private JButton addButton, subtractButton, multiplyButton, divideButton, clearButton;

    public Calculator() {
        // Set up the frame
        JFrame frame = new JFrame("Simple Calculator");
        frame.setSize(400, 300);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new BorderLayout());

        // Heading at the top
        JLabel headingLabel = new JLabel("edSlash Coding Hub Calculator", JLabel.CENTER);
        headingLabel.setFont(new Font("Arial", Font.BOLD, 22));
        headingLabel.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0));
        frame.add(headingLabel, BorderLayout.NORTH);

        // Create the form panel
        JPanel formPanel = new JPanel(new GridLayout(5, 2, 10, 10));
        formPanel.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));

        // Number 1 Input
        JLabel num1Label = new JLabel("Number 1:");
        num1Field = new JTextField();
        formPanel.add(num1Label);
        formPanel.add(num1Field);

        // Number 2 Input
        JLabel num2Label = new JLabel("Number 2:");
        num2Field = new JTextField();
        formPanel.add(num2Label);
        formPanel.add(num2Field);

        // Result Display
        JLabel resultLabel = new JLabel("Result:");
        resultField = new JTextField();
        resultField.setEditable(false); // Result field is read-only
        formPanel.add(resultLabel);
        formPanel.add(resultField);

        // Operation Buttons
        addButton = new JButton("Add");
        subtractButton = new JButton("Subtract");
        multiplyButton = new JButton("Multiply");
        divideButton = new JButton("Divide");
        clearButton = new JButton("Clear");

        JPanel buttonPanel = new JPanel(new GridLayout(1, 5, 5, 5));
        buttonPanel.add(addButton);
        buttonPanel.add(subtractButton);
        buttonPanel.add(multiplyButton);
        buttonPanel.add(divideButton);
        buttonPanel.add(clearButton);

        // Add components to the frame
        frame.add(formPanel, BorderLayout.CENTER);
        frame.add(buttonPanel, BorderLayout.SOUTH);

        // Add Action Listeners using Lambdas
        ActionListener listener = e -> handleOperation(e.getActionCommand());
        addButton.addActionListener(listener);
        subtractButton.addActionListener(listener);
        multiplyButton.addActionListener(listener);
        divideButton.addActionListener(listener);
        clearButton.addActionListener(e -> clearFields());

        // Make the frame visible
        frame.setVisible(true);
    }

    private void handleOperation(String operation) {
        try {
            double num1 = Double.parseDouble(num1Field.getText().trim());
            double num2 = Double.parseDouble(num2Field.getText().trim());
            double result = 0;

            switch (operation) {
                case "Add" -> result = num1 + num2;
                case "Subtract" -> result = num1 - num2;
                case "Multiply" -> result = num1 * num2;
                case "Divide" -> {
                    if (num2 == 0) {
                        showError("Cannot divide by zero.");
                        return;
                    }
                    result = num1 / num2;
                }
            }

            resultField.setText(String.valueOf(result));
        } catch (NumberFormatException ex) {
            showError("Please enter valid numbers.");
        }
    }

    private void showError(String message) {
        JOptionPane.showMessageDialog(null, message, "Input Error", JOptionPane.ERROR_MESSAGE);
    }

    private void clearFields() {
        num1Field.setText("");
        num2Field.setText("");
        resultField.setText("");
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(Calculator::new);
    }
}

				
			
Simple Calculator using Java & Swing

Code Walkthrough

Main Components:
  • JFrame: The main window for the calculator.
  • JLabel: Displays text like “Number 1”, “Number 2”, and “Result”.
  • JTextField: Input fields for entering numbers and showing the result.
  • JButton: Buttons for arithmetic operations and clearing input.
  • JOptionPane: Used to display error messages.
Key Functions:
  1. handleOperation()

    • Performs the selected arithmetic operation.
    • Handles divide-by-zero cases.
  2. showError()

    • Displays error messages using JOptionPane.
  3. clearFields()

    • Resets all input and result fields.
  4. main()

    • Launches the application using SwingUtilities.invokeLater

How to Run the Application

  • Install the JDK on your system.
  • Open your preferred IDE or code editor.
  • Create a new Java project and add the Calculator.java file.
  • Compile and run the project.
    • You can run the program using the command line as well:
      javac Calculator.java
      java Calculator

User Interface Design

  • Top Section: Displays the title using a centered label.
  • Center Section: Contains input fields and result display in a GridLayout with padding.
  • Bottom Section: Contains operation buttons and a clear button arranged in a GridLayout.
Layout and Styling:
  • GridLayout: Used to align fields and buttons neatly.
  • Border Padding: Ensures proper spacing around components.
  • Font Styling: The title label uses a bold font for emphasis.

Code with a different layout

				
					import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
import java.util.Stack;

public class SimpleCalculator2 {
    private JTextField displayBox;
    private StringBuilder input = new StringBuilder();

    public SimpleCalculator2() {
        // Set up the frame
        JFrame frame = new JFrame("Simple Calculator");
        frame.setSize(400, 600);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new BorderLayout());

        // Display box
        displayBox = new JTextField();
        displayBox.setEditable(false);
        displayBox.setFont(new Font("Arial", Font.BOLD, 28));
        displayBox.setHorizontalAlignment(JTextField.RIGHT);
        displayBox.setPreferredSize(new Dimension(400, 80));
        frame.add(displayBox, BorderLayout.NORTH);

        // Button panel with GridLayout for better control
        JPanel buttonPanel = new JPanel(new GridLayout(5, 4, 5, 5)); // 5 rows, 4 columns
        buttonPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));

        // Button labels for the calculator
        String[] buttonLabels = {
                "C", "←", "%", "/",
                "7", "8", "9", "*",
                "4", "5", "6", "-",
                "1", "2", "3", "+",
                "0", ".", "Result", "Reset"
        };

        // Add buttons dynamically to the panel
        ActionListener listener = e -> handleButtonClick(e.getActionCommand());
        for (String label : buttonLabels) {
            JButton button = createButton(label);
            button.addActionListener(listener);
            buttonPanel.add(button);
        }

        frame.add(buttonPanel, BorderLayout.CENTER);
        frame.setVisible(true);
    }

    // Create buttons with improved styling
    private JButton createButton(String label) {
        JButton button = new JButton(label);
        button.setFont(new Font("Arial", Font.BOLD, 18));
        button.setBackground(Color.LIGHT_GRAY);
        button.setForeground(Color.BLACK);
        button.setFocusPainted(false);
        button.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 2));
        return button;
    }

    private void handleButtonClick(String command) {
        switch (command) {
            case "Result" -> calculateResult();
            case "Reset" -> input.setLength(0);
            case "C" -> clearEntry();
            case "←" -> backspace();
            default -> input.append(command);
        }
        displayBox.setText(input.toString());
    }

    private void clearEntry() {
        input.setLength(0);
    }

    private void backspace() {
        if (input.length() > 0) {
            input.deleteCharAt(input.length() - 1);
        }
    }

    private void calculateResult() {
        try {
            double result = evaluateExpression(input.toString());
            input.setLength(0);
            input.append(result);
        } catch (Exception e) {
            input.setLength(0);
            input.append("Error");
        }
    }

    // Evaluate complex expressions
    private double evaluateExpression(String expression) {
        // Handle the percentage
        if (expression.contains("%")) {
            String[] parts = expression.split("%");
            if (parts.length > 1) {
                double base = evaluateExpression(parts[0]);
                double percent = evaluateExpression(parts[1]);
                return base * (percent / 100);
            }
        }

        Stack<Double> numbers = new Stack<>();
        Stack<Character> operators = new Stack<>();

        int i = 0;
        while (i < expression.length()) {
            char c = expression.charAt(i);

            if (Character.isDigit(c) || c == '.') {
                StringBuilder number = new StringBuilder();
                while (i < expression.length() && (Character.isDigit(expression.charAt(i)) || expression.charAt(i) == '.')) {
                    number.append(expression.charAt(i++));
                }
                numbers.push(Double.parseDouble(number.toString()));
                continue;
            } else if (c == '(') {
                operators.push(c);
            } else if (c == ')') {
                while (operators.peek() != '(') {
                    numbers.push(applyOperation(operators.pop(), numbers.pop(), numbers.pop()));
                }
                operators.pop();
            } else if (c == '+' || c == '-' || c == '*' || c == '/' || c == '^') {
                while (!operators.isEmpty() && hasPrecedence(c, operators.peek())) {
                    numbers.push(applyOperation(operators.pop(), numbers.pop(), numbers.pop()));
                }
                operators.push(c);
            }
            i++;
        }

        while (!operators.isEmpty()) {
            numbers.push(applyOperation(operators.pop(), numbers.pop(), numbers.pop()));
        }

        return numbers.pop();
    }

    private boolean hasPrecedence(char op1, char op2) {
        if ((op1 == '+' || op1 == '-') && (op2 == '*' || op2 == '/')) return false;
        return true;
    }

    private double applyOperation(char operator, double b, double a) {
        return switch (operator) {
            case '+' -> a + b;
            case '-' -> a - b;
            case '*' -> a * b;
            case '/' -> {
                if (b == 0) throw new ArithmeticException("Cannot divide by zero");
                yield a / b;
            }
            case '^' -> Math.pow(a, b);
            default -> 0;
        };
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(SimpleCalculator2::new);
    }
}

				
			

Code

				
					import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
import java.util.Stack;

public class SimpleCalculator2 {
    private JTextField displayBox;
    private StringBuilder input = new StringBuilder();

    public SimpleCalculator2() {
        // Set up the frame
        JFrame frame = new JFrame("Simple Calculator");
        frame.setSize(400, 600);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new BorderLayout());

        // Display box
        displayBox = new JTextField();
        displayBox.setEditable(false);
        displayBox.setFont(new Font("Arial", Font.BOLD, 28));
        displayBox.setHorizontalAlignment(JTextField.RIGHT);
        displayBox.setPreferredSize(new Dimension(400, 80));
        frame.add(displayBox, BorderLayout.NORTH);

        // Button panel with GridLayout for better control
        JPanel buttonPanel = new JPanel(new GridLayout(5, 4, 5, 5)); // 5 rows, 4 columns
        buttonPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));

        // Button labels for the calculator
        String[] buttonLabels = {
                "C", "←", "%", "/",
                "7", "8", "9", "*",
                "4", "5", "6", "-",
                "1", "2", "3", "+",
                "0", ".", "Result", "Reset"
        };

        // Add buttons dynamically to the panel
        ActionListener listener = e -> handleButtonClick(e.getActionCommand());
        for (String label : buttonLabels) {
            JButton button = createButton(label);
            button.addActionListener(listener);
            buttonPanel.add(button);
        }

        frame.add(buttonPanel, BorderLayout.CENTER);
        frame.setVisible(true);
    }

    // Create buttons with improved styling
    private JButton createButton(String label) {
        JButton button = new JButton(label);
        button.setFont(new Font("Arial", Font.BOLD, 18));
        button.setBackground(Color.LIGHT_GRAY);
        button.setForeground(Color.BLACK);
        button.setFocusPainted(false);
        button.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 2));
        return button;
    }

    private void handleButtonClick(String command) {
        switch (command) {
            case "Result" -> calculateResult();
            case "Reset" -> input.setLength(0);
            case "C" -> clearEntry();
            case "←" -> backspace();
            default -> input.append(command);
        }
        displayBox.setText(input.toString());
    }

    private void clearEntry() {
        input.setLength(0);
    }

    private void backspace() {
        if (input.length() > 0) {
            input.deleteCharAt(input.length() - 1);
        }
    }

    private void calculateResult() {
        try {
            double result = evaluateExpression(input.toString());
            input.setLength(0);
            input.append(result);
        } catch (Exception e) {
            input.setLength(0);
            input.append("Error");
        }
    }

    // Evaluate complex expressions
    private double evaluateExpression(String expression) {
        // Handle the percentage
        if (expression.contains("%")) {
            String[] parts = expression.split("%");
            if (parts.length > 1) {
                double base = evaluateExpression(parts[0]);
                double percent = evaluateExpression(parts[1]);
                return base * (percent / 100);
            }
        }

        Stack<Double> numbers = new Stack<>();
        Stack<Character> operators = new Stack<>();

        int i = 0;
        while (i < expression.length()) {
            char c = expression.charAt(i);

            if (Character.isDigit(c) || c == '.') {
                StringBuilder number = new StringBuilder();
                while (i < expression.length() && (Character.isDigit(expression.charAt(i)) || expression.charAt(i) == '.')) {
                    number.append(expression.charAt(i++));
                }
                numbers.push(Double.parseDouble(number.toString()));
                continue;
            } else if (c == '(') {
                operators.push(c);
            } else if (c == ')') {
                while (operators.peek() != '(') {
                    numbers.push(applyOperation(operators.pop(), numbers.pop(), numbers.pop()));
                }
                operators.pop();
            } else if (c == '+' || c == '-' || c == '*' || c == '/' || c == '^') {
                while (!operators.isEmpty() && hasPrecedence(c, operators.peek())) {
                    numbers.push(applyOperation(operators.pop(), numbers.pop(), numbers.pop()));
                }
                operators.push(c);
            }
            i++;
        }

        while (!operators.isEmpty()) {
            numbers.push(applyOperation(operators.pop(), numbers.pop(), numbers.pop()));
        }

        return numbers.pop();
    }

    private boolean hasPrecedence(char op1, char op2) {
        if ((op1 == '+' || op1 == '-') && (op2 == '*' || op2 == '/')) return false;
        return true;
    }

    private double applyOperation(char operator, double b, double a) {
        return switch (operator) {
            case '+' -> a + b;
            case '-' -> a - b;
            case '*' -> a * b;
            case '/' -> {
                if (b == 0) throw new ArithmeticException("Cannot divide by zero");
                yield a / b;
            }
            case '^' -> Math.pow(a, b);
            default -> 0;
        };
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(SimpleCalculator2::new);
    }
}

				
			
Simple Calculator

Project by Harshil Bansal, Team edSlash.