import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
class Calculator extends JFrame implements ActionListener {
private final String[] KEY = {"7", "8", "9", "AC", "4", "5", "6", "+", "1", "2", "3", "-", "0", "e", "pi", "*", "sqrt",
"%", "x*x", "/", "(", ")", ".", "="};
private JButton key[] = new JButton[KEY.length];
private JTextArea Text = new JTextArea("0");
private String click = "";
private JTextArea History=new JTextArea();
private JPanel jp=new JPanel();
private JScrollPane gundong=new JScrollPane(History);
private JLabel label=new JLabel("History");
public Calculator() {
super("简单计算器");//计算器界面命名
this.setLayout(null);
Text.setBounds(20, 5, 255, 40);//设置文本框大小
Text.setBackground(new Color(67, 138, 121));
Text.setAlignmentX(Component.LEFT_ALIGNMENT);//文本框内容左对齐
Text.setEditable(false);//文本框不能修改内容
this.add(Text);
History.setBounds(90,40,50,70);
History.setAlignmentX(Component.LEFT_ALIGNMENT);
History.setEditable(false);
label.setBounds(300,15,100,20);
jp.setBounds(290,40,160,285);
jp.setLayout(new GridLayout());
gundong.setViewportView(History);
gundong.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
History.setLineWrap(true);//换行
History.setSelectedTextColor(Color.cyan);
History.setWrapStyleWord(true);
jp.add(gundong);
this.add(jp);
this.setLayout(null);
this.add(label);
int x = 20, y = 55;
for (int i = 0; i < KEY.length; i++) {
key[i] = new JButton();
key[i].setText(KEY[i]);
key[i].setBounds(x, y, 60, 40);
if (x < 215) {
x = x + 65;
} else {
x = 20;
y = y + 45;
}
this.add(key[i]);
}
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
for (int i = 0; i < KEY.length; i++) {
key[i].addActionListener(this);
}
this.setResizable(false);
this.setBounds(500, 200, 460, 380);
this.setVisible(true);
}
// 事件监听
public void actionPerformed(ActionEvent e) {
// 获得事件源的标签
String label = e.getActionCommand();
if (label=="AC"||label=="=") {
History.setText(History.getText()+Text.getText());
Text.setText(this.click);
if (label.equals("=")) {//调用计算方法,得出最终结果
String[] s = infixtosuffix(this.click);
String result = suffix(s);
this.click = result + "";
//更行文本框,当前结果在字符串b中,并未删除,下一次输入接着此结果以实现连
Text.setText(this.click);
History.setText(History.getText()+"="+Text.getText()+"\n");
}else {
this.click="";
Text.setText("0");
}
} else if (label=="sqrt"){
String n = kaifang(this.click);
Text.setText(n);//使运算表达式显示在输入界面
History.setText(History.getText()+this.click+"^2"+"=");
this.click = n;
}else if (label=="x*x") {
String m = pingfang(this.click);
Text.setText(m);
this.click = m;
} else if (label=="e"||label=="pi") {
if (label=="e") {
String m = String.valueOf(2.71828);
this.click = this.click + m;
Text.setText(this.click);
}
if (label=="pi" ) {
String m = String.valueOf(3.14159265);
this.click = this.click + m;
Text.setText(this.click);
}
} else {
this.click = this.click + label;
Text.setText(this.click);
}
}
//将中缀表达式转换为后缀表达式
private String[] infixtosuffix(String str) {
String s = "";// 用于承接多位数的字符串
char[] opStack = new char[200];// 静态栈,对用户输入的操作符进行处理,用于存储运算符
String[] postQueue = new String[200];// 后缀表达式字符串数组,为了将多位数存储为独立的字符串
int top = -1, j = 0;// 静态指针top,控制变量j
for (int i = 0; i < str.length(); i++)// 遍历中缀表达式
{
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 suffix(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 String kaifang(String str) {
String result = "";
double a = Double.parseDouble(str), b = 0;
b = Math.sqrt(a);
result = String.valueOf(b);
return result;
}
//平方运算
public String pingfang(String str) {
String result = "";
double a = Double.parseDouble(str), b = 0;
b = Math.pow(a, 2);
result = String.valueOf(b);
return result;
}
public static void main(String[] args) {
Calculator a=new Calculator();
}
}