题目来源:大工慕课 链接
作者:Caleb Sung
题目要求
利用GUI实现一个计算器。点击一个按钮时,显示屏应该显示相应的数字。
下图为设计样板:
(MacOS真是随便写个Frame都可以这么好看呀……)
注1:本部分结束后,还将贴出教授写的简易版本。这个版本涉及计算的逻辑较为简单,但不能完整正常实现正常计算器的全部功能。此外本文还附有核心Java这本书的随书参考代码,其基于按键响应的编程思路也值得大家借鉴。
注2:电脑端用户可以通过左侧的目录按键快速定位到文章相应位置。
参考解答1(我的版本)
这道题属于较为综合的题,其中涉及计算的部分涉及了数据结构的相关知识。这部分我讲不做讲解,请自行考察学习。
本篇代码除主函数之外,只有一个类(类中的方法在下面分别列出)。下面给出的第一部分代码用于实现计算器的GUI本身:
class CalculatorFrame extends JFrame implements ActionListener {
String operator = "";
String input = "";
boolean flag = true;
JTextField display = new JTextField("Please input your formula:");
public CalculatorFrame() {
setTitle("Calculator");
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(250, 300);
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
setLocation(screenSize.width / 2 - getSize().width / 2, screenSize.height / 2 - getSize().height / 2);
display.setAlignmentY(RIGHT_ALIGNMENT);
add(display, BorderLayout.NORTH);
JPanel numPad = new JPanel();
numPad.setLayout(new GridLayout(4, 4));
JButton btnAdd = new JButton("+");
btnAdd.setForeground(Color.RED);
btnAdd.addActionListener(this);
JButton btnMinus = new JButton("-");
btnMinus.setForeground(Color.RED);
btnMinus.addActionListener(this);
JButton btnTimes = new JButton("*");
btnTimes.setForeground(Color.RED);
btnTimes.addActionListener(this);
JButton btnDivision = new JButton("/");
btnDivision.setForeground(Color.RED);
btnDivision.addActionListener(this);
JButton btnDot = new JButton(".");
btnDot.setForeground(Color.RED);
btnDot.addActionListener(this);
JButton btnEqu = new JButton("=");
btnEqu.setForeground(Color.RED);
btnEqu.addActionListener(this);
JButton[] btnNums = new JButton[10];
for (int i = 0; i < 10; ++i) {
btnNums[i] = new JButton("" + i);
btnNums[i].setForeground(Color.BLUE);
btnNums[i].addActionListener(this);
}
numPad.add(btnNums[7]);
numPad.add(btnNums[8]);
numPad.add(btnNums[9]);
numPad.add(btnDivision);
numPad.add(btnNums[4]);
numPad.add(btnNums[5]);
numPad.add(btnNums[6]);
numPad.add(btnTimes);
numPad.add(btnNums[1]);
numPad.add(btnNums[2]);
numPad.add(btnNums[3]);
numPad.add(btnMinus);
numPad.add(btnNums[0]);
numPad.add(btnDot);
numPad.add(btnEqu);
numPad.add(btnAdd);
add(numPad, BorderLayout.CENTER);
validate();
}
//下续
}
下面介绍在CalculatorFrame类中的两种Method:
1. 方法actionPerformed()
此方Method用于实现响应按键事件。
public void actionPerformed(ActionEvent e) {
int cnt = 0;
String actionCommand = e.getActionCommand();
if (actionCommand.equals("+") || actionCommand.equals("-") || actionCommand.equals("*")
|| actionCommand.equals("/"))
input += " " + actionCommand + " ";
else if (actionCommand.equals("=")) {
input += "=" + cmp(input);
display.setText(input);
input = "";
cnt = 1;
} else
input += actionCommand;
if (cnt == 0)
display.setText(input);
}
2. 方法calc()
此Method用于实现执行计算。
private String calc(String input) {
String str[];
str = input.split(" ");
Stack<Double> s = new Stack<Double>();
double m = Double.parseDouble(str[0]);
s.push(m);
for (int i = 1; i < str.length; i++) {
if (i % 2 == 1) {
if (str[i].compareTo("+") == 0) {
double help = Double.parseDouble(str[i + 1]);
s.push(help);
}
if (str[i].compareTo("-") == 0) {
double help = Double.parseDouble(str[i + 1]);
s.push(-help);
}
if (str[i].compareTo("*") == 0) {
double help = Double.parseDouble(str[i + 1]);
double ans = s.peek();//取栈顶
s.pop();//消栈
ans *= help;
s.push(ans);
}
if (str[i].compareTo("/") == 0) {
double help = Double.parseDouble(str[i + 1]);
double ans = s.peek();
s.pop();
ans /= help;
s.push(ans);
}
}
}
double ans = 0;
while (!s.isEmpty()) {
ans += s.peek();
s.pop();
}
String result = String.valueOf(ans);
return result;
}
参考解答2(教授简易版本)
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
/**
* A frame with a calculator panel.
*/
public class CalculatorFrame extends JFrame {
String lastCommand = "=";
double result = 0;
JTextField display = new JTextField();
boolean start = true;
public CalculatorFrame() {
setTitle("Swing Components");
setSize(300, 200);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
// Add the display
add(display, BorderLayout.NORTH);
// Define all Buttons
JButton btnAdd = new JButton("+");
JButton btnMinus = new JButton("-");
JButton btnTimes = new JButton("*");
JButton btnDivision = new JButton("/");
JButton btnDot = new JButton(".");
JButton btnEqu = new JButton("=");
btnAdd.addActionListener(new ArithmaticListener());
btnMinus.addActionListener(new ArithmaticListener());
btnTimes.addActionListener(new ArithmaticListener());
btnDivision.addActionListener(new ArithmaticListener());
btnEqu.addActionListener(new ArithmaticListener());
JButton[] btnNums = new JButton[10];
for (int i = 0; i < 10; ++i) {
btnNums[i] = new JButton("" + i);
btnNums[i].addActionListener(new NumberInputListener());
}
btnDot.addActionListener(new NumberInputListener());
// Add the number pad
JPanel p = new JPanel();
// Set 4*4 Grid Layout
p.setLayout(new GridLayout(4, 4));
p.add(btnNums[7]);
p.add(btnNums[8]);
p.add(btnNums[9]);
p.add(btnDivision);
p.add(btnNums[4]);
p.add(btnNums[5]);
p.add(btnNums[6]);
p.add(btnTimes);
p.add(btnNums[1]);
p.add(btnNums[2]);
p.add(btnNums[3]);
p.add(btnMinus);
p.add(btnNums[0]);
p.add(btnDot);
p.add(btnEqu);
p.add(btnAdd);
add(p, BorderLayout.CENTER);
pack();
}
class NumberInputListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
String num = e.getActionCommand();
if (start) {
display.setText(num);
start = false;
}
else
display.setText(display.getText()+num);
}
}
class ArithmaticListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
start = true;
String command = e.getActionCommand();
double x = Double.parseDouble(display.getText());
if (lastCommand.equals("+"))
result += x;
else if (lastCommand.equals("-"))
result -= x;
else if (lastCommand.equals("*"))
result *= x;
else if (lastCommand.equals("/"))
result /= x;
else if (lastCommand.equals("="))
result = x;
display.setText(""+result);
lastCommand = command;
}
}
}
参考解答(核心Java版本的代码)
Calculator.java
package calculator;
import java.awt.*;
import javax.swing.*;
/**
* @version 1.34 2015-06-12
* @author Cay Horstmann
*/
public class Calculator
{
public static void main(String[] args)
{
EventQueue.invokeLater(() -> {
CalculatorFrame frame = new CalculatorFrame();
frame.setTitle("Calculator");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
});
}
}
CalculatorFrame.java
package calculator;
import javax.swing.*;
/**
* A frame with a calculator panel.
*/
public class CalculatorFrame extends JFrame
{
public CalculatorFrame()
{
add(new CalculatorPanel());
pack();
}
}
CalculatorPanel.java
package calculator;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
/**
* A panel with calculator buttons and a result display.
*/
public class CalculatorPanel extends JPanel
{
private JButton display;
private JPanel panel;
private double result;
private String lastCommand;
private boolean start;
public CalculatorPanel()
{
setLayout(new BorderLayout());
result = 0;
lastCommand = "=";
start = true;
// add the display
display = new JButton("0");
display.setEnabled(false);
add(display, BorderLayout.NORTH);
ActionListener insert = new InsertAction();
ActionListener command = new CommandAction();
// add the buttons in a 4 x 4 grid
panel = new JPanel();
panel.setLayout(new GridLayout(4, 4));
addButton("7", insert);
addButton("8", insert);
addButton("9", insert);
addButton("/", command);
addButton("4", insert);
addButton("5", insert);
addButton("6", insert);
addButton("*", command);
addButton("1", insert);
addButton("2", insert);
addButton("3", insert);
addButton("-", command);
addButton("0", insert);
addButton(".", insert);
addButton("=", command);
addButton("+", command);
add(panel, BorderLayout.CENTER);
}
/**
* Adds a button to the center panel.
* @param label the button label
* @param listener the button listener
*/
private void addButton(String label, ActionListener listener)
{
JButton button = new JButton(label);
button.addActionListener(listener);
panel.add(button);
}
/**
* This action inserts the button action string to the end of the display text.
*/
private class InsertAction implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
String input = event.getActionCommand();
if (start)
{
display.setText("");
start = false;
}
display.setText(display.getText() + input);
}
}
/**
* This action executes the command that the button action string denotes.
*/
private class CommandAction implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
String command = event.getActionCommand();
if (start)
{
if (command.equals("-"))
{
display.setText(command);
start = false;
}
else lastCommand = command;
}
else
{
calculate(Double.parseDouble(display.getText()));
lastCommand = command;
start = true;
}
}
}
/**
* Carries out the pending calculation.
* @param x the value to be accumulated with the prior result.
*/
public void calculate(double x)
{
if (lastCommand.equals("+")) result += x;
else if (lastCommand.equals("-")) result -= x;
else if (lastCommand.equals("*")) result *= x;
else if (lastCommand.equals("/")) result /= x;
else if (lastCommand.equals("=")) result = x;
display.setText("" + result);
}
}