I'm currently making a calculator where I input the operation in a textbox and to the right of it, there is a button. If I press enter in the textbox or press the button, the answer or an error message should show up in a JLabel underneath. I'm able to somewhat show the input textbox and button but don't know how to show answer once button is clicked or enter is pressed in label.
Viewer
import javax.swing.JFrame;
public class CalculatorViewer {
public static void main(String[] args) {
JFrame frame = new CalculatorViewerFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("FontViewer");
frame.setVisible(true);
}
}
Frame
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class CalculatorViewerFrame extends JFrame {
private JLabel resultLabel;
private JTextField inputField;
private JButton button;
private ActionListener listener;
private static final int FRAME_WIDTH = 500;
private static final int FRAME_HEIGHT = 300;
public CalculatorViewerFrame() {
class Calculate implements ActionListener {
public void actionPerformed(ActionEvent event) {
String input = inputField.getText();
input = input.trim();
int x = 0,y=0;
String operator;
try {
x = Integer.parseInt(input.substring(0,input.indexOf(" ")));
} catch(InvalidExpressionException exception) {
resultLabel.setText("The first operand is not an integer");
}
if (input.indexOf(" ")==input.lastIndexOf(" ") || input.indexOf(" ")+1==input.lastIndexOf(" ")) {
operator = " ";
} else {
operator = input.substring(input.indexOf(" "), input.lastIndexOf(" "));
}
operator = operator.trim();
try {
y= Integer.parseInt(input.substring(input.lastIndexOf(" ")));
} catch(InvalidExpressionException exception) {
resultLabel.setText("The second operand is not an integer");
}
int answer;
String operation = x +" " + operator + y+ " = ";
switch (operator) {
case "+": answer = x + y;
resultLabel.setText(operation + answer);
resultLabel.repaint();
case "-": answer = x - y;
resultLabel.setText(operation + answer);
resultLabel.repaint();
case "*": answer = x * y;
switch (y) {
case 0: resultLabel.setText("Cannot divide by 0");
}
resultLabel.setText(operation + answer);
resultLabel.repaint();
case "/": answer = x / y;
resultLabel.setText(operation + answer);
resultLabel.repaint();
case "%": answer = x % y;
resultLabel.setText(operation + answer);
resultLabel.repaint();
default: resultLabel.setText("Illegal operator");
}
}
}
createInputPanel();
resultLabel = new JLabel();
add(resultLabel, BorderLayout.CENTER);
listener = new Calculate();
setSize(FRAME_WIDTH, FRAME_HEIGHT);
}
public void createInputPanel() {
JPanel inputPanel = createInputTextField();
JPanel compute = createButton();
JPanel controlPanel = new JPanel();
controlPanel.setLayout(new GridLayout(1,2));
controlPanel.add(inputPanel);
controlPanel.add(compute);
add(controlPanel, BorderLayout.NORTH);
}
private JPanel createInputTextField() {
inputField = new JTextField(20);
inputField.setEditable(true);
inputField.requestFocus();
inputField.setText("");
JPanel panel = new JPanel();
inputField.addActionListener(listener);
panel.add(inputField);
return panel;
}
public JPanel createButton() {
button = new JButton("Compute");
JPanel panel = new JPanel();
button.addActionListener(listener);
panel.add(button);
return panel;
}
}
Here are pictures of what it should look like/similar to.
Any help is greatly appreciated! Thank you.
I super agree with Scheintod to his feedback. I will leave that to him as he nailed it. I managed to optimize your code. See my comments inside the code and learn from it. I think this is your homework/project, is it? Lol.
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class CalculatorViewerFrame extends JFrame implements ActionListener { // you dont need to create sub class and
// implement ActionListener to it. You
// can do it here
private JLabel resultLabel;
private JTextField inputField;
private JButton button;
private static final int FRAME_WIDTH = 500;
private static final int FRAME_HEIGHT = 300;
public CalculatorViewerFrame() {
createInputPanel();
resultLabel = new JLabel();
add(resultLabel, BorderLayout.CENTER);
setSize(FRAME_WIDTH, FRAME_HEIGHT);
}
private void createInputPanel() { // set your modifier into private, it is not used from other class
JPanel inputPanel = createInputTextField();
JPanel compute = createButton();
JPanel controlPanel = new JPanel();
controlPanel.setLayout(new GridLayout(1, 2));
controlPanel.add(inputPanel);
controlPanel.add(compute);
add(controlPanel, BorderLayout.NORTH);
}
private JPanel createInputTextField() {
inputField = new JTextField(20);
inputField.setEditable(true);
inputField.requestFocus();
inputField.setText("");
JPanel panel = new JPanel();
inputField.addActionListener(this); // since you implemented it to this class. you can use `this` as your input in parameter addActionListener
panel.add(inputField);
return panel;
}
private JPanel createButton() { // set your modifier into private, it is not used from other class
button = new JButton("Compute");
JPanel panel = new JPanel();
button.addActionListener(this); // same thing with line 50
panel.add(button);
return panel;
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("Compute")) { // though you have only one action. always check for this as it
// tells what action event happened.
// parse and validate
String input = inputField.getText();
input = input.trim();
int x = 0, y = 0;
String operator;
try {
x = Integer.parseInt(input.substring(0, input.indexOf(" ")).trim());
} catch (NumberFormatException exception) { // check your catch exception too. Remove that is/are not relevant to your try block
resultLabel.setText("The first operand is not an integer");
return; // you need to stop the process from here. you are using resultLabel all the time and you setText into it.
}
if (input.indexOf(" ") == input.lastIndexOf(" ") || input.indexOf(" ") + 1 == input.lastIndexOf(" ")) {
operator = " ";
} else {
operator = input.substring(input.indexOf(" "), input.lastIndexOf(" "));
}
operator = operator.trim();
try {
y = Integer.parseInt(input.substring(input.lastIndexOf(" ")).trim()); // trim for white spaces.
} catch (NumberFormatException exception) {
resultLabel.setText("The second operand is not an integer");
return; // you need to stop the process from here. you are using resultLabel all the time and you setText into it.
}
compute(x, y, operator);
}
}
private void compute(int x, int y, String operator) { // you can move this block of code into another method as it
// is a new process.
int answer;
String operation = x + " " + operator + y + " = ";
switch (operator) {
case "+":
answer = x + y;
resultLabel.setText(operation + answer);
resultLabel.repaint();
break; // use break as it the process will continue. your case would be useless then.
case "-":
answer = x - y;
resultLabel.setText(operation + answer);
resultLabel.repaint();
break;
case "*":
answer = x * y; // you dont need to spam switch condition.
// if you are checking for one condition, use IF
if (y == 0) {
resultLabel.setText("Cannot divide by 0");
}
resultLabel.setText(operation + answer);
resultLabel.repaint();
break;
case "/":
answer = x / y;
resultLabel.setText(operation + answer);
resultLabel.repaint();
break;
case "%":
answer = x % y;
resultLabel.setText(operation + answer);
resultLabel.repaint();
break;
default:
resultLabel.setText("Illegal operator");
break;
}
}
}
To answer your question, how to show output. You need to use return in the method actionPerformed when it fell in catch block. Because you need to terminate the process.
Try to look this. When the error comes up, you set text to resultLabel. Saying "The operand is not an integer".
Then computation proceeds and you set a text again in resultLabel. What would be the value in resultLabel?
Cheers!