Volo
Volo

Reputation: 43

Text not appearing on TextField for GUI Calculator?

I've been making a GUI calculator, but I've run into a ditch. I know my code is only restricted to the '2' button, but that's because I've cut out all the numbers so the code can be shorter to be put on here. When I press two, I know the Actionlistener is activated because the System.out.println will print out 2. But it won't appear on my Text Field, where did I go wrong?

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.util.Random;
import java.awt.FlowLayout;

public class CalculatorY {
    public static  JPanel panel = new JPanel(new GridLayout(5, 5));
    public static JButton one, two, three, four, five, six, seven, eight, nine, zero, equal;
    public static JTextField result;
    public static boolean add, sub, mult, div;

    public static void main(String[] args) {
        JFrame frame = new JFrame("Rohini and Sonika's Calculator");
        result = new JTextField(null,90);
        two = new JButton("2");
        equal = new JButton("=");
        two.addActionListener(new button());
        panel.setLayout(new GridLayout(5, 5, 5, 25));
        panel.setLayout(new FlowLayout());
        panel.add(result, BorderLayout.NORTH);
        panel.add(two);
        frame.setVisible(true);
        frame.setSize(200, 400);
        frame.setResizable(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setContentPane(panel);
    }

    public static class button implements ActionListener {
        public void actionPerformed(ActionEvent event) {

            String command = event.getActionCommand();
            String text = result.getText();
            int textLength = text.length();
            String letterValueOne = null;
            String letterValueTwo = null;
            boolean operation = false; 
                    if (operation == false) {
                        if (letterValueOne == null) {
                            letterValueOne = "2";   
                            System.out.println(letterValueOne);
                            result.setText(letterValueOne);
                        } else {
                            letterValueOne = letterValueOne + "2";
                            result.setText(letterValueOne);
                        }
                    } else {
                        if (letterValueTwo == null) {
                            letterValueTwo = "2";
                        } else {
                            letterValueTwo = letterValueTwo + "2";
                        }
                    }
        }
    }
}

Upvotes: 2

Views: 968

Answers (3)

Hovercraft Full Of Eels
Hovercraft Full Of Eels

Reputation: 285430

Yours is a layout/size/placement issue. Myself, I would do things a bit differently including:

  • Nest JPanels each using its own layout so that simple layout managers can produce complex GUI's.
  • The main JPanel could use a BorderLayout, and you could place the display JTextField in its BorderLayout.PAGE_START (or NORTH) position. This will constrain the JTextField to fill the top of the main JPanel but would not allow it to go beyond this JPanel as a FlowLayout could.
  • The JButtons could be held in a separate JPanel that uses a GridLayout
  • And this button containing JPanel could be placed into the main JPanel in its BorderLayout.CENTER position.

For example,

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.util.HashMap;
import java.util.Map;

import javax.swing.*;

public class CalcEg {
    private static final float BTN_FONT_SIZE = 20f;
    private static final String[][] BTN_LABELS = {
            { "sqr", "sqrt", "exp", "clr" },
            { "7", "8", "9", "-" },
            { "4", "5", "6", "+" },
            { "1", "2", "3", "/" },
            { "0", ".", " ", "=" }
    };
    private static final int GAP = 4;
    private static final String NUMBERS = "0123456789.";
    private JPanel mainPanel = new JPanel(new BorderLayout(GAP, GAP));
    private JPanel buttonPanel = new JPanel();
    private JTextField display = new JTextField();
    private Map<String, Runnable> operationMap = new HashMap<>();

    public CalcEg() {
        int rows = BTN_LABELS.length;
        int cols = BTN_LABELS[0].length;
        buttonPanel.setLayout(new GridLayout(rows, cols, GAP, GAP));
        for (String[] btnLabelRow : BTN_LABELS) {
            for (String btnLabel : btnLabelRow) {
                if (btnLabel.trim().isEmpty()) {
                    buttonPanel.add(new JLabel());
                } else {
                    JButton btn = createButton(btnLabel);
                    if (NUMBERS.contains(btnLabel)) {
                        Action action = new NumberButtonAction(btnLabel);
                        btn.setAction(action);
                    } else {
                        Action action = new OperationBtnAction(btnLabel);
                        btn.setAction(action);
                    }
                    buttonPanel.add(btn);
                }
            }
        }
        display.setFont(display.getFont().deriveFont(BTN_FONT_SIZE));
        display.setEditable(false);
        display.setFocusable(false);
        display.setBackground(Color.white);

        mainPanel.setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
        mainPanel.add(buttonPanel, BorderLayout.CENTER);
        mainPanel.add(display, BorderLayout.PAGE_START);

        fillOperationMap();
    }

    private void fillOperationMap() {
        operationMap.put("sqr", () -> {
            String displayText = display.getText();
            try {
                double value = Double.parseDouble(displayText);
                value *= value;
                display.setText(Double.toString(value));
            } catch (NumberFormatException e) {
                String message = "Invalid entry";
                String title = "Number Entry Error";
                JOptionPane.showMessageDialog(mainPanel, message, title, JOptionPane.ERROR_MESSAGE);
            }
        });
        operationMap.put("sqrt", () -> {
            String displayText = display.getText();
            try {
                double value = Double.parseDouble(displayText);
                value = Math.sqrt(value);
                display.setText(Double.toString(value));
            } catch (NumberFormatException e) {
                String message = "Invalid entry";
                String title = "Number Entry Error";
                JOptionPane.showMessageDialog(mainPanel, message, title, JOptionPane.ERROR_MESSAGE);
            }
        });
        operationMap.put("exp", () -> {
            String displayText = display.getText();
            try {
                double value = Double.parseDouble(displayText);
                value = Math.exp(value);
                display.setText(Double.toString(value));
            } catch (NumberFormatException e) {
                String message = "Invalid entry";
                String title = "Number Entry Error";
                JOptionPane.showMessageDialog(mainPanel, message, title, JOptionPane.ERROR_MESSAGE);
            }
        });
        operationMap.put("clr", () -> {
            display.setText("");
        });
        operationMap.put("+", () -> {
            //....
        });
    }


    private JButton createButton(String btnLabel) {
        JButton button = new JButton(btnLabel);
        button.setFont(button.getFont().deriveFont(BTN_FONT_SIZE));
        return button;
    }

    public JComponent getMainComponent() {
        return mainPanel;
    }

    private class NumberButtonAction extends AbstractAction {
        public NumberButtonAction(String name) {
            super(name);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            String displayText = display.getText();
            displayText += getValue(NAME);

            try {
                Double.parseDouble(displayText);
                
            } catch (NumberFormatException e1) {
                String message = "Invalid entry";
                String title = "Number Entry Error";
                JOptionPane.showMessageDialog(mainPanel, message, title, JOptionPane.ERROR_MESSAGE);
                return;
            }
            display.setText(displayText);
        }
    }

    private class OperationBtnAction extends AbstractAction {
        public OperationBtnAction(String name) {
            super(name);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            Runnable operation = operationMap.get(getValue(NAME));
            if (operation != null) {
                operation.run();
            }
            // TODO: implement all math operations based on the name of the button
        }
    }

    private static void createAndShowGui() {
        CalcEg mainPanel = new CalcEg();

        JFrame frame = new JFrame("CalcEg");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(mainPanel.getMainComponent());
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

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

Which would create this GUI:

enter image description here

Upvotes: 1

intrigus
intrigus

Reputation: 216

It actually appears on your textField, you simply don't see it, if it's a small window. change

result = new JTextField(null,90);

to

result = new JTextField(null,10);

Then you should see the "2". Another problem:I don't know if this error exists because you removed unnecessary code but Eclipse shows me that e.g.

if (letterValueTwo == null) {
    letterValueTwo = "2";
                    } else {
                        HERE//letterValueTwo = letterValueTwo + "2";
                    }

"//Here" can't be reached, because you first assign letterValueTwo == null and that's why your else branch will be never executed.

Upvotes: 0

It does put a 2 in the text field! You can see this by clicking in the text-field, pressing Ctrl-A, then Ctrl-C, then pasting somewhere else.

new JTextField(null, 90) creates a text field that is wide enough to hold 90 characters, but this is wider than the frame (at least on my system) so it gets cut off at the sides. If you maximize the frame, you should see the 2.

Some possible solutions are:

  • Make the frame bigger. Note that you can't predict how wide "90 columns" might be on some other computer, so you can't know how big is big enough.

  • Make the text field smaller. This has the same problem.

  • Call frame.pack(); at the end. This makes the frame big enough to hold all the components in it. FlowLayout will arrange them in a line; you might want to go back to using BorderLayout.

Upvotes: 4

Related Questions