一、需求分析:
1.实现简单的加减乘除四则运算
2.在四则运算的基础上实现平方,开方等运算
3.检测运算时是否错误
4.界面整洁美观,操作逻辑简单明了
二、开发工具以及开发环境:
1.编程语言:java
2.开发环境:IntelliJ IDEA Community Edition 2022
三、关键算法的实现:
1.swing awt在Java中对于窗口的实现
awt:
AWT(Abstract Window Toolkit),中文译为抽象窗口工具包,该包提供了一套与本地图形界面进行交互的接口,是Java提供的用来建立和设置Java的图形用户界面的基本工具。AWT中的图形函数与操作系统所提供的图形函数之间有着一一对应的关系,称之为peers,当利用AWT编写图形用户界面时,实际上是在利用本地操作系统所提供的图形库。由于不同操作系统的图形库所提供的样式和功能是不一样的,在一个平台上存在的功能在另一个平台上则可能不存在。为了实现Java语言所宣称的“一次编写,到处运行(write once, run anywhere)”的概念,AWT不得不通过牺牲功能来实现平台无关性,也即AWT所提供的图形功能是各种操作系统所提供的图形功能的交集。
第一次进行对窗口编程的实现:
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class Main {
public static void main(String[] args) {
Frame frame = new Frame("计算器");//建立窗口标题
frame.setVisible(true);//设置窗口可见
frame.setSize(500,700);//设置窗口的长宽
frame.setBackground(Color.white);//设置窗口的颜色
frame.setLocation(500,100);//设置窗口的位置
frame.setResizable(true);//设置是否能改变窗口的大小
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});//实现使用窗口右上角的关闭键的关闭窗口这个进程
}
}
计算器的实现
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Objects;
import javax.swing.*;
public class calculator extends JFrame implements ActionListener {
private final String[] Keys = {"7", "8", "9", "AC", "4", "5", "6", "-", "1", "2", "3", "+", "0", "e", "pi", "/", "sqrt",
"%", "^", "*", "(", ")", ".", "="};
private JButton keys[] = new JButton[Keys.length];
private JTextArea resultText = new JTextArea("0");
private JTextArea historyText = new JTextArea();
private JPanel jp = new JPanel();
private JScrollPane roll1 = new JScrollPane(resultText);
private JScrollPane roll2 = new JScrollPane(historyText);
private JLabel label1 = new JLabel("历史纪录");
private String b = "";
private int flagkuohao = 0;
private int flagdian = 0;
public calculator() {
super("科学计算器");
resultText.setBounds(40, 20, 255, 115);
resultText.setAlignmentX(RIGHT_ALIGNMENT);
resultText.setEditable(false);
historyText.setBounds(300, 40, 250, 370);
historyText.setAlignmentX(LEFT_ALIGNMENT);
historyText.setEditable(false);
label1.setBounds(300, 15, 100, 20);
jp.setBounds(290, 40, 250, 370);
jp.setLayout(new GridLayout());
JPanel jp1 = new JPanel();
jp1.setBounds(20, 18, 255, 115);
jp1.setLayout(new GridLayout());
resultText.setLineWrap(true);
resultText.setWrapStyleWord(true);
resultText.setSelectedTextColor(Color.black);
historyText.setLineWrap(true);
historyText.setSelectedTextColor(Color.red);
historyText.setWrapStyleWord(true);
roll1.setViewportView(resultText);
roll2.setViewportView(historyText);
roll1.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
roll2.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
jp1.add(roll1);
jp.add(roll2);
this.add(jp1);
this.add(jp);
this.setLayout(null);
this.add(label1);
int x = 20, y = 150;
for (int i = 0; i < Keys.length; i++) {
keys[i] = new JButton();
keys[i].setText(Keys[i]);
keys[i].setBounds(x, y, 60, 40);
if (x < 215) {
x += 65;
} else {
x = 20;
y += 45;
}
this.add(keys[i]);
}
for (int i = 0; i < Keys.length; i++)// 每个按钮都注册事件监听器
{
keys[i].addActionListener(this);
}
this.setResizable(false);
this.setBounds(500, 200, 567, 480);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
this.setBackground(Color.black);
}
public void actionPerformed(ActionEvent e) {
String label = e.getActionCommand();
if (Objects.equals(label, "=")) {
resultText.setText(this.b);
historyText.setText(historyText.getText() + resultText.getText());
if (label.equals("=")) {
String[] s = behind(this.b);
String result = Result(s);
this.b = result + "";
resultText.setText(this.b);
historyText.setText(historyText.getText() + "=" + resultText.getText() + "\n");
}
} else if (Objects.equals(label, "AC")) {
this.b = "";
resultText.setText("0");
} else if (Objects.equals(label, "^2")) {
String m = Power(this.b);
resultText.setText(this.b + "^2" + "=");
} else if (label.equals("sqrt")) {
String m = Sqrt(this.b);
resultText.setText("sqrt" + "(" + this.b + ")" + m);
historyText.setText(historyText.getText() + this.b + "^2" + "=");
this.b = m;
} else if (Objects.equals(label, "e") || Objects.equals(label, "pi")) {
if (label.equals("e")) {
String m = String.valueOf(2.71828);//将e的值以字符串的形式传给m
this.b = this.b + m;//保留显示m之前输入的运算符或数字字符继续下一步运算
resultText.setText(this.b);
}
if (label.equals("pi")) {
String m = String.valueOf(3.14159265);
this.b = this.b + m;
resultText.setText(this.b);
}
} else if (label.equals("(")) {
flagkuohao++;
this.b = this.b + label;
resultText.setText(this.b);
} else if (label.equals(")")) {
if (flagkuohao > 0) {
this.b = this.b + label;
resultText.setText(this.b);
flagkuohao--;
} else {
}//控制有括号的数量
} else {
this.b = this.b + label;
resultText.setText(this.b);
}
}
public String Sqrt(String str) {
String result = "";
double a = Double.parseDouble(str);
double b = 0;
b = Math.sqrt(a);
result = String.valueOf(b);
return result;
}
public String Power(String str) {
String result = "";
double a = Double.parseDouble(str);
double b = 0;
b = Math.pow(a, 2);
result = String.valueOf(b);
return result;
}
public String[] behind(String str) {
String s = "";// 用于承接多位数的字符串
char[] opStack = new char[100];// 静态栈,对用户输入的操作符进行处理,用于存储运算符
String[] postQueue = new String[100];// 后缀表达式字符串数组,为了将多位数存储为独立的字符串
int top = -1, j = 0;// 静态指针top,控制变量j
for (int i = 0; i < str.length(); i++)// 遍历中缀表达式
// indexof函数,返回字串首次出现的位置;charAt函数返回index位置处的字符;
{
if ("0123456789.".indexOf(str.charAt(i)) >= 0) // 遇到数字字符的情况直接入队
{
s = "";// 作为承接字符,每次开始时都要清空
for (; i < str.length() && "0123456789.".indexOf(str.charAt(i)) >= 0; i++) {
s = s + str.charAt(i);
}
i--;
postQueue[j] = s;// 数字字符直接加入后缀表达式
j++;
} else if ("(".indexOf(str.charAt(i)) >= 0) {// 遇到左括号
top++;
opStack[top] = str.charAt(i);// 左括号入栈
} else if (")".indexOf(str.charAt(i)) >= 0) {// 遇到右括号
for (; ; )// 栈顶元素循环出栈,直到遇到左括号为止
{
if (opStack[top] != '(') {// 栈顶元素不是左括号
postQueue[j] = opStack[top] + "";// 栈顶元素出栈
j++;
top--;
} else { // 找到栈顶元素是左括号
top--;// 删除栈顶左括号
break;// 循环结束
}
}
} else if ("*%/+-".indexOf(str.charAt(i)) >= 0)// 遇到运算符
{
if (top == -1) {// 若栈为空则直接入栈
top++;
opStack[top] = str.charAt(i);
} else if ("*%/".indexOf(opStack[top]) >= 0) {// 当栈顶元素为高优先级运算符时,让栈顶元素出栈进入后缀表达式后,当前运算符再入栈
postQueue[j] = opStack[top] + "";
j++;
opStack[top] = str.charAt(i);
} else {
top++;
opStack[top] = str.charAt(i);// 当前元素入栈
}
}
}
while (top != -1) {// 遍历结束后将栈中剩余元素依次出栈进入后缀表达式
postQueue[j] = opStack[top] + "";
j++;
top--;
}
return postQueue;
}
public String Result(String[] str) {
String[] Result = new String[100];// 顺序存储的栈,数据类型为字符串
int Top = -1;// 静态指针Top
for (int i = 0; str[i] != null; i++) {
if ("+-*%/".indexOf(str[i]) < 0) { //遇到数字,直接入栈
Top++;
Result[Top] = str[i];
}
if ("+-*%/".indexOf(str[i]) >= 0)// 遇到运算符字符,将栈顶两个元素出栈计算并将结果返回栈顶
{
double x, y, n;
x = Double.parseDouble(Result[Top]);// 顺序出栈两个数字字符串,并转换为double类型
Top--;
y = Double.parseDouble(Result[Top]);
Top--;
if ("*".indexOf(str[i]) >= 0) {
n = y * x;
Top++;
Result[Top] = String.valueOf(n);// 将运算结果重新入栈
}
if ("/".indexOf(str[i]) >= 0) {
if (x == 0)// 被除数不允许为0
{
String s = "error!";
return s;
} else {
n = y / x;
Top++;
Result[Top] = String.valueOf(n);// 将运算结果重新入栈
}
}
if ("%".indexOf(str[i]) >= 0) {
if (x == 0)// 被除数不允许为0
{
String s = "error!";
return s;
} else {
n = y % x;
Top++;
Result[Top] = String.valueOf(n);// 将运算结果重新入栈
}
}
if ("-".indexOf(str[i]) >= 0) {
n = y - x;
Top++;
Result[Top] = String.valueOf(n);// 将运算结果重新入栈
}
if ("+".indexOf(str[i]) >= 0) {
n = y + x;
Top++;
Result[Top] = String.valueOf(n);// 将运算结果重新入栈
}
}
}
return Result[Top];
}
public static void main(String[] args) {
calculator a = new calculator();
}
}