本文参考自https://blog.csdn.net/CCSUXWZ/article/details/78239089,侵删。
一.UI界面的布置
窗体中放置三个JPanel面板,第一个面板放数字与操作符组件(0-9,+ - * / . =),4*4网格布局,置于窗体中部;第二个面板放文本框,置于顶部;第三个面板放 清空 按钮与 历史记录 按钮,置于底部。
窗体为边界布局。
按钮上的数字/操作符使用数组存储,一个for循环就能创建完按钮并添加到JPanel面板中。
String[] butname= {"7","8","9","+","4","5","6","-","1","2","3","*",".","0","=","/"};
for (int i=0;i
文本框的创建
JTextField result_Jtf;
result_Jtf=new JTextField(30);
result_Jtf.setHorizontalAlignment(JTextField.RIGHT);//右对齐
result_Jtf.setEditable(false);//文本框禁止编辑
panel2.setLayout(new BorderLayout());//边界布局
panel2.add(result_Jtf);//文本框置于panel2组件中
frame.add(panel2,BorderLayout.NORTH);//置于顶部
清空与历史记录 按钮
设置了一个Hiatory数组用于存储记录,仅能显示最近五条,每次显示一条。
count_H变量记录按下该按钮的次数,作为数组的下标
JButton CE=new JButton("CE");
JButton history=new JButton("历史记录");
panel3.add(CE);
panel3.add(history);
frame.add(panel3, BorderLayout.SOUTH);
二.添加事件监听器
str存储表达式。
所有操作符的按钮除=之外被按下时,都添加其代表操作符到str中,并且添加时在其前后加上空格,便于用split()分割成子串。
if (actionbut.equals("+")||actionbut.equals("-")||actionbut.equals("*")||actionbut.equals("/"))
{
str=str+" "+actionbut+" ";
}
数字则直接添加到str中。
str=str+actionbut;
按下=号时,对表达式求值,将结果打印到文本框中,对按下等号的次数计数,因为只显示最近五条记录,所以次数还要对5取模,让它的范围在[0,4]之间,然后把str存入到历史记录的数组中,最后将str置空。
str=str+actionbut+calculate(str);//calculate()为表达式求值函数
result_Jtf.setText(str);//打印到文本框中
count_equ=count_equ%5;//仅保存最近五条记录
History[count_equ]=str;//存到历史记录数组中
count_equ++;
str=" ";
flag=0;
其中,对表达式求值,具体操作如下:
使用split()分割str,并将子串存到一个String数组中。(为什么不用double而用Double,当然是Double有很多方法可以使用呀,比如我们等下就要用到的parseDouble(),它可以把String转成Double类型,而Double虽然是个类,但可以直接与基本数据类型进行四则运算,后面就可以直接计算啦)
创建一个栈,数据为Double型的,存储所有的数字。
由于str的初始值为" ",也不知道为什么分割值没把它去掉,反正它就占据了数组第一位的位置(也就是下标为0)。所以导致了数组中下标为奇数的是数字,偶数是操作符。因此我们把下标为1的元素先丢进栈中。
for循环的i从2开始。判断i是否为偶数,是则对该位上的操作符进行判断。
+:直接将后一位数字(Arr[i+1])入栈
-:取负后入栈
*:将栈顶元素出栈,与Arr[i+1]进行乘运算后将结果入栈
/:将栈顶元素出栈,将进行除运算的结果入栈
最后将栈中的所有数字相加,把结果转为字符串形式返回,与原str一起打印到文本框中。
public String calculate(String str)
{
String[] comput=str.split(" ");//分割操作符与数字
Stack stack=new Stack();//存储数据
stack.push(Double.parseDouble(comput[1]));
for (int i=2;i
关于程序的一点小问题:窗体出现时窗口一片空白,人为放大或缩小后才会显示界面。也不知道为啥,明明设了窗体可见。
2019.3.4
原因是我设置可见那句代码放得太前面了,应该放在后面。
一点想法:文本框只能显示一行,如果要显示历史记录的话,使用文本域是比较好的,由于历史记录是完成基本运算后额外添加的功能,然后,改成文本域的话,要改动好多地方,就懒得再动了emmmm。
以上。
完整代码如下
/*
在未输入数字之前,不能输入操作符
*/
package calculator;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.Stack;
public class calculator
{
String str=" ";//文本框的内容
JFrame frame;
JTextField result_Jtf;
JPanel panel1,panel2,panel3;
String[] History=new String[5];
int count_H=0;//按下 历史记录 的次数
int count_equ=0;//按下 = 的次数
public calculator ()
{
frame=new JFrame("Calculator");
frame.setLayout(new BorderLayout());
frame.setLocation(300,200);
frame.setSize(450,300);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
result_Jtf=new JTextField(30);
result_Jtf.setHorizontalAlignment(JTextField.RIGHT);//右对齐
result_Jtf.setEditable(false);//文本框禁止编辑
panel3=new JPanel();
panel3.setLayout(new GridLayout(1,2,5,5));
JButton CE=new JButton("CE");
JButton history=new JButton("历史记录");
panel3.add(CE);
panel3.add(history);
frame.add(panel3, BorderLayout.SOUTH);
panel1=new JPanel();
panel2=new JPanel();
panel1.setLayout(new GridLayout(4,4,5,5));//4*4网格布局
panel2.setLayout(new BorderLayout());//边界布局
panel2.add(result_Jtf);//文本框置于panel2组件中
CE.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
str=" ";
result_Jtf.setText(str);
}
});
history.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
count_H=count_H%5;//只能显示最近五条记录
String his_str=History[count_H];
result_Jtf.setText(his_str);
count_H++;
str=" ";
}
});
String[] butname= {"7","8","9","+","4","5","6","-","1","2","3","*",".","0","=","/"};
for (int i=0;i stack=new Stack();//存储数据
stack.push(Double.parseDouble(comput[1]));
for (int i=2;i