9

We were asked to make a simple GUI calculator, and I used getSource() to detect the buttons, because that's what they taught us. It works by typing the first and second value and then choosing the operation. It worked.

But I made a mistake, because they want us to make the numbers also be buttons, just like a real calculator. So how do I get the value of each button using getSource()? Like when I press button 1 and 2 is equal to 3. Here's what I've done:

import java.awt.*; import java.awt.event.*; public class SimpleCalculator implements ActionListener { // Containers private Frame f; private Panel p1, p2, p3, p4; // Components private Label l1, l2, l3; private TextField tf1, tf2, tf3; private Button bAdd, bSub, bMul, bDiv, bClear; public SimpleCalculator() { f = new Frame("My First GUI App"); p1 = new Panel(); p2 = new Panel(); p3 = new Panel(); p4 = new Panel(); l1 = new Label("First: "); l2 = new Label("Second: "); l3 = new Label("Result: "); tf1 = new TextField(15); tf2 = new TextField(15); tf3 = new TextField(15); bAdd = new Button("+"); bSub = new Button("-"); bMul = new Button("*"); bDiv = new Button("/"); bClear = new Button("C"); } public void launchFrame() { // Use the default layout manager of the Panel (FlowLayout) p1.add(l1); p1.add(tf1); p2.add(l2); p2.add(tf2); p3.add(l3); p3.add(tf3); p4.add(bAdd); p4.add(bSub); p4.add(bMul); p4.add(bDiv); p4.add(bClear); // Change the layout manager of the Frame. // Use GridLayout(4, 1) f.setLayout(new GridLayout(4, 1)); f.add(p1); f.add(p2); f.add(p3); f.add(p4); f.pack(); f.setVisible(true); // Register event handlers bAdd.addActionListener(this); bSub.addActionListener(this); bMul.addActionListener(this); bDiv.addActionListener(this); bClear.addActionListener(this); f.addWindowListener(new MyCloseButtonHandler()); } // Override the actionPerformed method public void actionPerformed(ActionEvent ae) { Object source = ae.getSource(); double num1, num2, result = 0.0; if (tf1.getText() != null && tf2.getText() != null) { num1 = Double.parseDouble(tf1.getText()); num2 = Double.parseDouble(tf2.getText()); if (source == bAdd) result = num1 + num2; else if (source == bSub) result = num1 - num2; else if (source == bMul) result = num1 * num2; else if (source == bDiv) result = num1 / num2; else if (source == bClear) { tf1.setText("0.0"); tf2.setText("0.0"); tf3.setText("0.0"); } else { } // tf3.setText(new Double(result).toString()); tf3.setText("" + result); } } private class MyCloseButtonHandler extends WindowAdapter { public void windowClosing(WindowEvent we) { System.exit(0); } } public static void main(String args[]) { SimpleCalculator sc = new SimpleCalculator(); sc.launchFrame(); } } 
1
  • which line/part of code creates a problem? Commented Sep 29, 2019 at 10:18

2 Answers 2

19

I would tend to have each button for the numbers, as well as each button for operands. Add text to a text field that is the 'Input/Output'.

Also have a button = (equals). When the = button is activated, call the ScriptEngine to evaluate the content of the I/O text field and write the result back to it.

Example

Calculated input = Calculated output

import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.border.EmptyBorder; import java.util.ArrayList; // Script package introduced in Java 1.6 import javax.script.ScriptEngineManager; import javax.script.ScriptEngine; import javax.script.ScriptException; class ScriptEngineCalculator implements ActionListener, KeyListener { private final JTextField io = new JTextField(15); private final ArrayList<JButton> controls = new ArrayList<>(); private final JPanel ui = new JPanel(new BorderLayout(2, 2)); private ScriptEngine engine; ScriptEngineCalculator() { initUI(); } public final void initUI() { // Obtain a reference to the JavaScript engine engine = new ScriptEngineManager().getEngineByExtension("js"); JPanel text = new JPanel(new GridLayout(0, 1, 3, 3)); ui.add(text, BorderLayout.PAGE_START); Font font = io.getFont(); font = font.deriveFont(font.getSize() * 1.8f); io.setFont(font); io.setHorizontalAlignment(SwingConstants.TRAILING); io.setFocusable(false); text.add(io); JPanel buttons = new JPanel(new GridLayout(4, 4, 2, 2)); ui.add(buttons, BorderLayout.CENTER); String[] keyValues = { "7", "8", "9", "/", "4", "5", "6", "*", "1", "2", "3", "-", "0", ".", "C", "+" }; for (String keyValue : keyValues) { addButton(buttons, keyValue); } JButton equals = new JButton("="); configureButton(equals); ui.add(equals, BorderLayout.LINE_END); ui.setBorder(new EmptyBorder(5, 5, 5, 5)); } public JComponent getUI() { return ui; } public void addButton(Container c, String text) { JButton b = new JButton(text); configureButton(b); c.add(b); } public void configureButton(JButton b) { Font f = b.getFont(); b.setFont(f.deriveFont(f.getSize() * 1.5f)); b.addActionListener(this); b.addKeyListener(this); controls.add(b); } public void calculateResult() { try { Object result = engine.eval(io.getText()); if (result == null) { io.setText("Output was 'null'"); } else { io.setText(result.toString()); } } catch (ScriptException se) { io.setText(se.getMessage()); } } @Override public void actionPerformed(ActionEvent ae) { String command = ae.getActionCommand(); switch (command) { case "C": io.setText(""); break; case "=": calculateResult(); break; default: io.setText(io.getText() + command); break; } } private JButton getButton(String text) { for (JButton button : controls) { String s = button.getText(); if (text.endsWith(s) || (s.equals("=") && (text.equals("Equals") || text.equals("Enter")))) { return button; } } return null; } /* START - Because I hate mice. */ @Override public void keyPressed(KeyEvent ke) { } @Override public void keyReleased(KeyEvent ke) { String s = KeyEvent.getKeyText(ke.getKeyCode()); JButton b = getButton(s); if (b != null) { b.requestFocusInWindow(); b.doClick(); } } @Override public void keyTyped(KeyEvent ke) { } /* END - Because I hate mice. */ public static void main(String[] args) { SwingUtilities.invokeLater(() -> { ScriptEngineCalculator sc = new ScriptEngineCalculator(); JFrame f = new JFrame("Calculet"); f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); f.setContentPane(sc.getUI()); f.pack(); f.setMinimumSize(f.getSize()); f.setLocationByPlatform(true); f.setVisible(true); }); } } 
Sign up to request clarification or add additional context in comments.

4 Comments

That code works good of course. But dont you think thats a poor OO Code? Never mind, I am sure you are much more experienced than me.
@Mohaimin "But dont you think thats a poor OO Code?" It is an SSCCE. SSCCEs are excused from many things, including an iota of 'OO design'. The idea is to pick up some ideas from the SSCCE, then adapt them into your design. Or to put that another way 'Batteries not included'. ;)
@Andrew: I understand. I was surprised to see that kind of code from an experienced person I am very new in StackOverflow so I am not aware of many things. I am learning :)
4

You can check if your source is a Button (not actually necessary since you should know it is only called from a button), typecast to a button, and use .getText():

String sourceText; if (ae.getSource() instanceof Button) { sourceText = ((Button)ae.getSource()).getText(); } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.