import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.Vector;
import java.math.BigDecimal;
import javax.swing.UIManager;
public class Calculat {
String str1="0"; // 操作数1,为了程序的安全,初值设置为0
String str2="0"; // 操作数2
String signal="+"; // 运算符
String result="";// 运算结果
// 以下k1至k5为状态开关
int k1=1;// 开关1用于选择输入方向,将要写入str1或str2
int k2=1;// 开关2用于记录符号键的次数,如果 k2>1 说明进行的是多符号运算
int k3=1;// 开关3用于标识 str1 是否可以被清0 ,等于1时可以,不等于1时不能被清0
int k4=1;// 开关4用于标识 str2 是否可以被清0,等于1时可以,不等于1时不能被清0
int k5=1;// 开关5用于控制小数点可否被录入,等于1时可以,不为1时,输入的小数点被丢掉
JButton store; // store的作用类似于寄存器,用于记录是否连续按下符号键
@SuppressWarnings("rawtypes")//忽略rawtypes警告信息
Vector vt=new Vector(20, 10);
// 声明各个UI组件对象并初始化
JFrame frame=new JFrame("Calculator");//JFrame是java里的一个窗体类,创建一个JFrame类的实例
//设置主窗口出现在屏幕上的位置
//frame.setLocation(300, 200);
//设置窗体不能调大小
//frame.setResizable(false);
JTextField result_TextField=new JTextField(result, 20);//JTextField是一个轻量级组件,允许编辑单行文本,构造一个用result和20列的新TextField
JButton clear_Button=new JButton("AC");//创建AC按钮
JButton button0=new JButton("0");//创建0按钮
JButton button1=new JButton("1");//创建1按钮
JButton button2=new JButton("2");//创建2按钮
JButton button3=new JButton("3");//创建3按钮
JButton button4=new JButton("4");//创建4按钮
JButton button5=new JButton("5");//创建5按钮
JButton button6=new JButton("6");//创建6按钮
JButton button7=new JButton("7");//创建7按钮
JButton button8=new JButton("8");//创建8按钮
JButton button9=new JButton("9");//创建9按钮
JButton button_Dian=new JButton(".");//创建.按钮
JButton button_jia=new JButton("+");//创建+按钮
JButton button_jian=new JButton("-");//创建-按钮
JButton button_cheng=new JButton("*");//创建*按钮
JButton button_chu=new JButton("/");//创建/按钮
JButton button_dy=new JButton("=");//创建=按钮
// 计算机类的构造器
public Calculat() {
// 为按钮设置等效键,可以通过对应的键盘按键来代替点击它
button0.setMnemonic(KeyEvent.VK_0);//按下Alt+0
button1.setMnemonic(KeyEvent.VK_1);//按下Alt+1
button2.setMnemonic(KeyEvent.VK_2);//按下Alt+2
button3.setMnemonic(KeyEvent.VK_3);//按下Alt+3
button4.setMnemonic(KeyEvent.VK_4);//按下Alt+4
button5.setMnemonic(KeyEvent.VK_5);//按下Alt+5
button6.setMnemonic(KeyEvent.VK_6);//按下Alt+6
button7.setMnemonic(KeyEvent.VK_7);//按下Alt+7
button8.setMnemonic(KeyEvent.VK_8);//按下Alt+8
button9.setMnemonic(KeyEvent.VK_9);//按下Alt+9
// 设置文本框为右对齐,使输入和结果都靠右显示
result_TextField.setHorizontalAlignment(JTextField.RIGHT);
// 将UI组件添加进容器内
JPanel pan = new JPanel();//创建面板组件的一个实例pan
pan.setLayout(new GridLayout(4, 4, 5, 5));//设置4行4列边距为5像素的表格布局
pan.add(button7);//设置pan对象的边距
pan.add(button8);
pan.add(button9);
pan.add(button_chu);
pan.add(button4);
pan.add(button5);
pan.add(button6);
pan.add(button_cheng);
pan.add(button1);
pan.add(button2);
pan.add(button3);
pan.add(button_jian);
pan.add(button0);
pan.add(button_Dian);
pan.add(button_dy);
pan.add(button_jia);
pan.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));//创建一个框,头部、底部、左、右都为5像素
JPanel pan2=new JPanel();
pan2.setLayout(new BorderLayout());//设置布局为边框布局,分东南西北中5个方位
pan2.add(result_TextField, BorderLayout.WEST);//将显示结果的文本框添加到pan2
pan2.add(clear_Button, BorderLayout.EAST);//将AC按钮添加到pan2
// 设置主窗口出现在屏幕上的位置
frame.setLocation(300, 200);//窗口最初位置
frame.setResizable(false); // 设置窗体不能调大小
frame.getContentPane().setLayout(new BorderLayout());//设置一个具有hgap为横向间距、vgap为纵向间距的边框布局
frame.getContentPane().add(pan2, BorderLayout.NORTH);//将pan2放到边框上方
frame.getContentPane().add(pan, BorderLayout.CENTER);//将pan放到边框中间
frame.pack();//根据窗口里面的布局及组件的preferedSize来确定frame的最佳大小
frame.setVisible(true);//窗口显示frame对象
// 事件处理程序
// 数字键响应事件
class Listener implements ActionListener {
@SuppressWarnings("unchecked")//忽略unchecked的警告信息
public void actionPerformed(ActionEvent e) {
String ss=((JButton) e.getSource()).getText();//获取事件源,并从事件源获取输入数据
store=(JButton) e.getSource();//读取存储的符号键
vt.add(store);//将符号键添加到vt中
if (k1==1) //输入是操作数1的部分,判断是否可以清零
{
if (k3==1)
{
str1="";
k5=1;// 还原开关k5状态
}
str1=str1+ss;//当输入完成后,需要给 k3 的值加 1,保证 操作数 1 不会被清空。并且还需要将操作数 1 打印到结果栏
k3=k3+1;
result_TextField.setText(str1);// 显示结果
}
else if (k1==2) //输入操作数是2的部分,判断是否可以清零
{
if (k4==1)
{
str2="";
k5=1; // 还原开关k5状态
}
str2=str2+ss;//当输入完成后,需要给 k4 的值加 1,保证 操作数 2 不会被清空。并且还需要将操作数 2 打印到结果栏
k4=k4+1;
result_TextField.setText(str2);//显示结果
}
}
}
// 输入的运算符号的处理
class Listener_signal implements ActionListener {
@SuppressWarnings("unchecked")
public void actionPerformed(ActionEvent e) {
String ss2=((JButton) e.getSource()).getText();//获取事件源,并从事件源获取输入数据
store=(JButton) e.getSource();//读取存储的符号键
vt.add(store);//将符号键添加到vt中去
if (k2==1)
{
k1=2;// 开关 k1 为 1 时向数 1 写输入值,为2时向数2写输入值。
k5=1;//可以输入小数点
signal=ss2;//只能输入一个符号
k2=k2+1;// 按符号键的次数
}
else
{
int a=vt.size();//表示输入的长度,读取上次的输入
JButton c=(JButton) vt.get(a - 2);//获取后面的运算符
if (!(c.getText().equals("+"))&& !(c.getText().equals("-"))&& !(c.getText().equals("*"))&& !(c.getText().equals("/")))//判断输入若不是这些的符号,就说明要进行多次运算
{
cal();//调用calc()运算并将结果存入str1中
str1=result;
k1=2;// 开关 k1 为 1 时,向数 1 写值,为2时向数2输入
k5=1;//可以输入小数点
k4=1;//可以连续计算
signal=ss2;//signal存储此次输入的符号
}
k2=k2+1;//增加已经输入的符号的次数
}
}
}
// 清除键的逻辑(Clear)
class Listener_clear implements ActionListener {
@SuppressWarnings("unchecked")
public void actionPerformed(ActionEvent e) {
store=(JButton) e.getSource();//读入存储的符号键
vt.add(store);//将符号键添加到vt中去
k5=1;//将所有的值清零或置为初值
k2=1;
k1=1;
k3=1;
k4=1;
str1="0";
str2="0";
signal="";
result="";
result_TextField.setText(result);//显示结果
vt.clear();
}
}
// 等于键的逻辑
class Listener_dy implements ActionListener {
@SuppressWarnings("unchecked")
public void actionPerformed(ActionEvent e) {
store=(JButton) e.getSource();//按键按下后,调用calc()函数,还原开关的值
vt.add(store);
cal();
// 还原各个开关的状态
k1=1;
k2=1;
k3=1;
k4=1;
str1=result;
}
}
// 小数点的处理
class Listener_xiaos implements ActionListener {
@SuppressWarnings("unchecked")
public void actionPerformed(ActionEvent e) {
store=(JButton) e.getSource();//获取相应源
vt.add(store);//将相应源添加到vt中去
if (k5==1)
{
String ss2=((JButton) e.getSource()).getText();//获取事件源,并从事件源获取输入的数据
if (k1==1) //输入是操作数1的部分,判断是否可以清零
{
if (k3==1)
{
str1="";
k5=1; // 还原开关k5状态
}
str1=str1+ss2;
k3=k3+1;
result_TextField.setText(str1);//显示结果
}
else if (k1==2) //输入是操作数2的部分,判断是否可以清零
{
if (k4==1)
{
str2="";
k5=1;// 还原开关k5的状态
}
str2=str2+ss2;
k4=k4+1;
result_TextField.setText(str2);//显示结果
}
}
k5=k5+1;
}
}
// 注册各个监听器,即绑定事件响应逻辑到各个UI组件上
//监听等于键
Listener_dy jt_dy=new Listener_dy();
button_dy.addActionListener(jt_dy);
// 监听数字键
Listener jt=new Listener();
button7.addActionListener(jt);
button8.addActionListener(jt);
button9.addActionListener(jt);
button4.addActionListener(jt);
button5.addActionListener(jt);
button6.addActionListener(jt);
button1.addActionListener(jt);
button2.addActionListener(jt);
button3.addActionListener(jt);
button0.addActionListener(jt);
// 监听符号键
Listener_signal jt_signal=new Listener_signal();
button_jia.addActionListener(jt_signal);
button_jian.addActionListener(jt_signal);
button_cheng.addActionListener(jt_signal);
button_chu.addActionListener(jt_signal);
// 监听清除键
Listener_clear jt_c=new Listener_clear();
clear_Button.addActionListener(jt_c);
// 监听小数点键
Listener_xiaos jt_xs=new Listener_xiaos();
button_Dian.addActionListener(jt_xs);
// 窗体关闭事件的响应程序
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);//退出程序
}
});
}
// 计算逻辑
public void cal() {
double a2;// 操作数1
double b2;// 操作数2
String c=signal;// 运算符
double result2=0;// 运算结果
if (c.equals(""))
{
result_TextField.setText("Please input operator");
}
else
{
// 手动处理小数点的问题
if (str1.equals("."))
str1="0.0";
if (str2.equals("."))
str2="0.0";
a2=Double.valueOf(str1).doubleValue();//转换字符串为double型
b2=Double.valueOf(str2).doubleValue();
if (c.equals("+"))
{
result2=a2+b2;
}
if (c.equals("-"))
{
result2=a2-b2;
}
if (c.equals("*"))
{
BigDecimal m1=new BigDecimal(Double.toString(a2));//为保证精度,将double存入大的浮点数类型BigDecimal中
BigDecimal m2=new BigDecimal(Double.toString(b2));
result2=m1.multiply(m2).doubleValue();
}
if (c.equals("/"))
{
if (b2==0)
{
result2=0;
}
else
{
result2=a2/b2;
}
}
result=((new Double(result2)).toString());
result_TextField.setText(result);
}
}
@SuppressWarnings("unused")
public static void main(String[] args) {
// 设置程序显示的界面风格
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowaLookAndFeel");//Windows窗体风格
/*Metal 风格(默认):javax.swing.plaf.metal.MetalLookAndFeel
更换为 Motif 风格:com.sun.java.swing.plaf.motif.MotifLookAndFeel
更换为 Mac 风格:com.sun.java.swing.plaf.mac.MacLookAndFeel
更换为 GTK 风格:com.sun.java.swing.plaf.gtk.GTKLookAndFeel*/
}
catch (Exception e)
{
e.printStackTrace();
}
Calculat cal=new Calculat();
}
}