项目目标和主要内容
学习图形界面的设计,利用 MFC 应用程序(Java swing 或 QT 框架,或 C#)创建基于对话框的应用程序,添加按钮、编辑框等控件;
能通过界面按钮控件输入并实现算术表达式,输入的表达式即时在控件中显示,按下“=”按钮能实现运算,并将运算结果输出在控件中显示。能通过界面按钮控件输入并实现算术表达式,输入的表达式即时在控件中显示,按下“=”按钮能实现运算,并将运算结果输出在控件中显示;
算术表达式求解,是指算术表达式中包括加、减、乘、除、括号等运算符,能求解包含括号的四则混合运算;并且能够检验表达式的合法性。
项目的主要功能
计算器能够实现混合运算的算术表达式求解;
输入时有足够的容错机制,来尽量避免用户输入不合规的算术表达式。
项目总体框架
系统详细设计
Java Swing搭建的GUI
1)编辑计算器整体界面大小
·界面的大小,初始位置等基础设置
2)添加组件
·以表格的排列形式添加按键,添加输入以及显示用的文本框
3)实现组件功能
·为按钮添加对应的监听事件,使文本框显示对应的输入与输出结果
判断用户输入的字符的类型
1)判断用户输入的是数字、运算符号或“=”
·根据输入的字符类型,决定应用的算法,并作出一些用户友好的容错设置
·在之前的运行中,数字在以小数点“.”开头时程序会忽略掉小数点只取整数,如用户输入“.5”,程序会将数字修改为“5”,经过修改后通过添加判断条件,当出现类似“.5”的小数点前无数的情况,系统会将该数修改为如“0.5”的数
输出结果
1)根据算法生成结果
·将计算结果返回至输出结果文本框中
关键算法分析
·具体算法
判断输入的字符类型
若输入字符为数字:
①若最新输入数字字符两侧没有运算符,则与先前或之后输入的数字字符共同组成运算用的数字。若与运算符相连,则将运算符之前的所有数字字符组成运算用的数字。
②若与运算符相连,则将运算符之前的所有数字字符组成运算用的数字。
若输入字符为运算符:
①算式的开头与结尾被禁止输入运算符,且禁止多个运算符相连。
②将运算符与其相邻的两个运算用数字共同形成算式。
若输入字符为括号:
①在没有左括号以及括号内无内容时被禁止输入右括号。
②左右括号内的内容将提升算术优先级,如括号中的加减法优先级高于括号外的乘除法。
③在算式结尾缺少所需数量的右括号时,程序会在不修改算式优先级的情况下补充右括号。
若输入字符为等号:
①计算算式的结果。
②将结果返回至输出文本框显示。
若输入字符为退格与清空:
①退格时,清除上一个输入的字符。
②清空时,清空所有输入与输出内容。
源代码
package 计算器;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Stack;
public class Calculator extends JFrame implements ActionListener {
String s = null;
int PointNumber = 0; //记录小数点数量
int EqualNumber = 0; //记录等号数量
int LNum = 0; //记录左括号的数量
int RNum = 0; //记录右括号的数量
Button b_0;
Button b_1;
Button b_2;
Button b_3;
Button b_4;
Button b_5;
Button b_6;
Button b_7;
Button b_8;
Button b_9;
Button b_plus;
Button b_minus;
Button b_multiply;
Button b_divide;
Button b_decimalpoint;
Button b_leftbracket;
Button b_rightbracket;
Button b_empty;
Button b_equal;
Button b_backspace;
TextField input;
TextField output;
JPanel upper;
JPanel below;
public Calculator() {
JFrame frame = new JFrame("计算器");
frame.setLayout(null);
frame.setFont(new Font("宋体", Font.BOLD, 25));
frame.setBounds(200, 200, 550, 625);
b_0 = new Button("0");
b_0.addActionListener(this);
b_1 = new Button("1");
b_1.addActionListener(this);
b_2 = new Button("2");
b_2.addActionListener(this);
b_3 = new Button("3");
b_3.addActionListener(this);
b_4 = new Button("4");
b_4.addActionListener(this);
b_5 = new Button("5");
b_5.addActionListener(this);
b_6 = new Button("6");
b_6.addActionListener(this);
b_7 = new Button("7");
b_7.addActionListener(this);
b_8 = new Button("8");
b_8.addActionListener(this);
b_9 = new Button("9");
b_9.addActionListener(this);
b_plus = new Button("+");
b_plus.addActionListener(this);
b_minus = new Button("_");
b_minus.addActionListener(this);
b_multiply = new Button("*");
b_multiply.addActionListener(this);
b_divide = new Button("/");
b_divide.addActionListener(this);
b_decimalpoint = new Button(".");
b_decimalpoint.addActionListener(this);
b_leftbracket = new Button("(");
b_leftbracket.addActionListener(this);
b_rightbracket = new Button(")");
b_rightbracket.addActionListener(this);
b_empty = new Button("empty");
b_empty.addActionListener(this);
b_equal = new Button("=");
b_equal.addActionListener(this);
b_backspace = new Button("backspace");
b_backspace.addActionListener(this);
input = new TextField();
input.addActionListener(this);
input.setBounds(20, 140, 170, 40);
input.setFont(new Font("宋体", Font.BOLD, 30));
output = new TextField(1000);
output.addActionListener(this);
output.setBounds(20, 40, 550 - 50, 80);
output.setFont(new Font("宋体", Font.BOLD, 35));
upper = new JPanel(null);
below = new JPanel(new GridLayout(5, 4));
upper.setBounds(0, 0, 550, 200);
upper.setBackground(new Color(250, 250, 250));
upper.add(input);
upper.add(output);
below.setBounds(0, 200, 550, 400);
below.setBackground(Color.black);
below.add(b_leftbracket);
below.add(b_rightbracket);
below.add(b_empty);
b_empty.setFont(new Font("宋体", Font.BOLD, 15));
b_backspace.setFont(new Font("宋体", Font.BOLD, 15));
below.add(b_backspace);
below.add(b_7);
below.add(b_8);
below.add(b_9);
below.add(b_divide);
below.add(b_4);
below.add(b_5);
below.add(b_6);
below.add(b_multiply);
below.add(b_1);
below.add(b_2);
below.add(b_3);
below.add(b_minus);
below.add(b_decimalpoint);
below.add(b_0);
below.add(b_equal);
below.add(b_plus);
frame.setVisible(true);
frame.add(upper);
frame.add(below);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void actionPerformed(ActionEvent e) {
if (e.getSource().equals(b_0)) {
s = input.getText();
if (s.length() <= 8) {
if (!s.equals("0") && EqualNumber != 1) {
input.setText(s + "0");
}
}
}
if (e.getSource().equals(b_1)) {
s = input.getText();
if (s.length() <= 8 && EqualNumber != 1) {
if (s.equals("0") || s.equals("")) {
input.setText("1");
} else {
input.setText(s + "1");
}
}
}
if (e.getSource().equals(b_2)) {
s = input.getText();
if (s.length() <= 8 && EqualNumber != 1) {
if (s.equals("0") || s.equals("")) {
input.setText("2");
} else {
input.setText(s + "2");
}
}
}
if (e.getSource().equals(b_3)) {
s = input.getText();
if (s.length() <= 8 && EqualNumber != 1) {
if (s.equals("0") || s.equals("")) {
input.setText("3");
} else {
input.setText(s + "3");
}
}
}
if (e.getSource().equals(b_4)) {
s = input.getText();
if (s.length() <= 8 && EqualNumber != 1) {
if (s.equals("0") || s.equals("")) {
input.setText("4");
} else {
input.setText(s + "4");
}
}
}
if (e.getSource().equals(b_5)) {
s = input.getText();
if (s.length() <= 8 && EqualNumber != 1) {
if (s.equals("0") || s.equals("")) {
input.setText("5");
} else {
input.setText(s + "5");
}
}
}
if (e.getSource().equals(b_6)) {
s = input.getText();
if (s.length() <= 8 && EqualNumber != 1) {
if (s.equals("0") || s.equals("")) {
input.setText("6");
} else {
input.setText(s + "6");
}
}
}
if (e.getSource().equals(b_7)) {
s = input.getText();
if (s.length() <= 8 && EqualNumber != 1) {
if (s.equals("0") || s.equals("")) {
input.setText("7");
} else {
input.setText(s + "7");
}
}
}
if (e.getSource().equals(b_8)) {
s = input.getText();
if (s.length() <= 8 && EqualNumber != 1) {
if (s.equals("0") || s.equals("")) {
input.setText("8");
} else {
input.setText(s + "8");
}
}
}
if (e.getSource().equals(b_9)) {
s = input.getText();
if (s.length() <= 8 && EqualNumber != 1) {
if (s.equals("0") || s.equals("")) {
input.setText("9");
} else {
input.setText(s + "9");
}
}
}
if (e.getSource().equals(b_decimalpoint)) {
s = input.getText();
if (PointNumber == 0) {
input.setText(s + ".");
PointNumber = 1;
}
}
if (e.getSource().equals(b_plus)) {
s = input.getText();
char[] ch1 = s.toCharArray();
int length1 = s.length() - 1;
String S = output.getText();
char[] ch2 = S.toCharArray();
int length2 = S.length() - 1;
//当数字为空或为0或数字的最后一位是小数点时不作处理
if ((length2 != -1 && ch2[length2] == ')') || (!s.equals("0") && !s.equals("") && ch1[length1] != '.')) {
input.setText("");
output.setText(output.getText() + s + "+");
}
}
if (e.getSource().equals(b_minus)) {
s = input.getText();
char[] ch1 = s.toCharArray();
int length1 = s.length() - 1;
String S = output.getText();
char[] ch2 = S.toCharArray();
int length2 = S.length() - 1;
if ((length2 != -1 && ch2[length2] == ')') || (!s.equals("0") && !s.equals("") && ch1[length1] != '.')) {
input.setText("");
output.setText(output.getText() + s + "-");
}
}
if (e.getSource().equals(b_multiply)) {
s = input.getText();
char[] ch1 = s.toCharArray();
int length1 = s.length() - 1;
String S = output.getText();
char[] ch2 = S.toCharArray();
int length2 = S.length() - 1;
if ((length2 != -1 && ch2[length2] == ')') || (!s.equals("0") && !s.equals("") && ch1[length1] != '.')) {
input.setText("");
output.setText(output.getText() + s + "*");
}
}
if (e.getSource().equals(b_divide)) {
s = input.getText();
char[] ch1 = s.toCharArray();
int length1 = s.length() - 1;
String S = output.getText();
char[] ch2 = S.toCharArray();
int length2 = S.length() - 1;
if ((length2 != -1 && ch2[length2] == ')') || (!s.equals("0") && !s.equals("") && ch1[length1] != '.')) {
input.setText("");
output.setText(output.getText() + s + "÷");
}
}
if (e.getSource().equals(b_leftbracket)) {
if (!input.getText().equals("0") && !input.getText().contentEquals("")) {
output.setText(output.getText() + input.getText());
}
s = output.getText();
char[] ch = s.toCharArray();
int length = s.length() - 1;
if (length == -1 || ch[length] == '+' || ch[length] == '-' || ch[length] == '*' || ch[length] == '÷' || ch[length] == '(') {
output.setText(output.getText() + '(');
LNum++;
}
}
if (e.getSource().equals(b_rightbracket)) {
if (!input.getText().equals("0")) {
output.setText(output.getText() + input.getText());
input.setText("");
}
s = output.getText();
char[] ch = s.toCharArray();
int length = s.length() - 1;
if (Character.isDigit(ch[length]) && LNum > RNum) {
RNum++;
output.setText(output.getText() + ')');
}
}
if (e.getSource().equals(b_empty)) {
input.setText("0");
output.setText("");
LNum = 0;
RNum = 0;
PointNumber = 0;
EqualNumber = 0;
}
if (e.getSource().equals(b_backspace)) {
int i = input.getText().length();
int j = output.getText().length();
output.setText(output.getText().substring(0, j - 1));
input.setText(input.getText().substring(0, i - 1));
}
if (e.getSource().equals(b_equal)) {
s = input.getText();
if (!s.equals("0") && !s.equals("")) {
output.setText(output.getText() + s);
}
if (EqualNumber == 0) {
input.setText("");
//补全右括号
for (int i = 0; i < LNum - RNum; i++) {
output.setText(output.getText() + ')');
}
//算法
String[] ans = new String[100];
int Size = 0;
Stack<Character> Operator = new Stack<>();
s = output.getText();
char[] value = s.toCharArray();
int length = value.length;
for (int j = 0; j < length; j++) {
//当数组元素为数字时
if (value[j] >= '0' && value[j] <= '9') {
double Number = value[j] - '0';
//继续遍历,直到不是数字和小数点
//记录小数点是否出现
int point = 0;
//记录小数点出现后的位数
int bit = 1;
if (j == length - 1) {
ans[Size++] = String.valueOf(Number);
}
for (j++; j < length; j++) {
if ((value[j] < '0' || value[j] > '9') && value[j] != '.') {
j--;
ans[Size++] = String.valueOf(Number);
break;
}
if (value[j] == '.') {
point = 1;
continue;
}
if (value[j] >= '0' && value[j] <= '9') {
//当小数点没有出现时和没出现时分开讨论
if (point == 0) {
Number = Number * 10 + (value[j] - '0');
} else {
Number = Number + Math.pow(10, -bit) * (value[j] - '0');
bit++;
}
}
}
} else {
//考虑运算符
if (value[j] == '(') {
Operator.push('(');
} else if (value[j] == ')') {
while (!Operator.peek().equals('(')) {
ans[Size++] = String.valueOf(Operator.peek());
Operator.pop();
}
Operator.pop();
} else {
if (Operator.empty()) {
Operator.push(value[j]);
} else {
while (true) {
if (Operator.empty()) {
Operator.push(value[j]);
break;
}
char operator1 = Operator.peek();
if ((value[j] == '*' || value[j] == '÷') && (operator1 == '+' || operator1 == '-') || (operator1 == '(' || operator1 == ')')) {
Operator.push(value[j]);
break;
} else {
ans[Size++] = String.valueOf(Operator.peek());
Operator.pop();
}
}
}
}
}
}
while (!Operator.empty()) {
ans[Size++] = String.valueOf(Operator.peek());
Operator.pop();
}
Stack<Double> Last = new Stack<>();
for (int i = 0; i < Size; i++) {
String s1 = ans[i];
char[] element = s1.toCharArray();
if (element[0] >= '0' && element[0] <= '9') {
Last.push(Double.parseDouble(s1));
} else {
double num1 = Last.pop();
double num2 = Last.pop();
double num3 = 0;
if (element[0] == '+')
num3 = num2 + num1;
else if (element[0] == '-')
num3 = num2 - num1;
else if (element[0] == '*')
num3 = num2 * num1;
else if (element[0] == '÷')
num3 = num2 / num1;
Last.push(num3);
}
}
output.setText(output.getText() + "=" + Last.pop());
EqualNumber = 1;
}
}
}
public static void main(String[] args) {
Calculator SCalculator = new Calculator();
}
}
计算器界面展示: