importjava.awt.BorderLayout;importjava.awt.CheckboxMenuItem;importjava.awt.Container;importjava.awt.GridLayout;importjava.awt.Menu;importjava.awt.MenuBar;importjava.awt.MenuItem;importjava.awt.event.ActionEvent;importjava.awt.event.ActionListener;importjavax.swing.JButton;importjavax.swing.JFrame;importjavax.swing.JOptionPane;importjavax.swing.JPanel;importjavax.swing.JTextField;importjavax.swing.text.html.HTMLDocument.HTMLReader.IsindexAction;publicclassCalextendsJFrameimplementsActionListener {//菜单MenuBar myMenuBar=newMenuBar();//JPanelJPanel pdisplay=newJPanel();
JPanel pm=newJPanel(newGridLayout(5,1,0,5));
JPanel pc=newJPanel(newGridLayout(1,3,5,0));
JPanel pb=newJPanel(newGridLayout(4,5,5,5));
JPanel pbc=newJPanel(newBorderLayout(5,5));
JPanel pbcm=newJPanel();static//显示JTextField tftext=newJTextField(25);
JTextField tfm=newJTextField(5);//按钮字符定义及按钮String strB[]={"MC","MR","MS","M+","Backspace","CE","C","7","8","9","/","sqrt","4","5","6","*","%","1","2","3","-","1/x","0","+/-",".","+","="};
JButton[] jb=newJButton[27];publicCal() {super("计算机-荞叶制作");
addMenu();
initDisplay();
initPbcm();
Container pane=this.getContentPane();
pane.setLayout(newBorderLayout(10,5));
pane.add(pdisplay, BorderLayout.NORTH);
pane.add(pbcm, BorderLayout.CENTER);this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);this.setBounds(300,200,400,260);this.setResizable(false);this.setVisible(true);
}//一些类变量staticStringBuilder text=newStringBuilder("0");//显示符StringBuilder number=newStringBuilder("0");//当前数.doublerightOper;//右数doubleleftOper;//左数doubleresult;//结果intoperator;//操作符,默认为0,没有操作符intisFloat=0;//0不是浮点型,1输入了一个.2真正的浮点booleanisZero=true;//0显示清空状态,不能输入0.输入1-9进入1状态.可以输入0-9进入2;booleanisNeg;//默认为正数booleanisExcp;//默认没有异常.StringBuilder m=newStringBuilder("0");//存储数串变量intisRightInput=0;//一次有效右输入,输入运算符后=1;再输入数字后=2;/*** number是用于给leftOper和rightOper赋值的.纯纯的能够转化为Double类型的StringBuilder.
* 当然text,number,m考虑到大量的String连接和转换,StringBuilder效率更高.
**/publicvoidactionPerformed(ActionEvent e) {
String cmd=e.getActionCommand();if(cmd=="0"||cmd=="1"||cmd=="2"||cmd=="3"||cmd=="4"||cmd=="5"||cmd=="6"||cmd=="7"||cmd=="8"||cmd=="9") {if(isExcp)//如果是三种错误之一,就不响应了.只有CE和C能够响应return;if(isRightInput==1)//如果是待一次有效右输入.也就是前一次输入的是运算符.isRightInput=2;//进阶真正的右输入if(isZero) {//处于清空状态number=newStringBuilder(cmd);//number直接为一个数字串isZero=false;//有一位数字后,不在处于清空.后面就可以输入运算符,单目,.,+/-}else{if(isFloat==1) {//待浮点状态,前一次输入的是.number.append('.');//number这时加入.isFloat=2;//真正的浮点.}
number.append(cmd);//数字后连接数字.if(number.charAt(0)=='0'&&isFloat!=2)//如果不是浮点,number.deleteCharAt(0);//但以0开头就删去.这种方法不优雅,但想不出更好的.}
text=number;//只要输入数字,无条件地显示.}elseif(cmd==".") {if(isExcp)return;if(isFloat==0)//如果不是浮点型isFloat=1;//待浮点型.}elseif(cmd=="+/-") {if(isZero||isExcp)//清空状态或异常.return;if(isNeg) {//如果是负数就变为正数,如果是正数就变为负数.isNeg=false;
number.deleteCharAt(0);//delete和insert操作可以推迟到完成数字输入状态后,根据isNeg来判断更好.}else{
isNeg=true;
number.insert(0,'-');
}
text=number;
}//双目运算功能elseif(cmd=="+"||cmd=="-"||cmd=="*"||cmd=="/") {if(isExcp)return;if(isRightInput==0)
isRightInput=1;//变为待一次有效右输入状态.if(isRightInput==2) {//如果已经是一次有效右输入了.就相当于'='.比如1+2+的时候.rightOper=Double.parseDouble(number.toString());//当前的number给右数.try{
result=Util.calculate(leftOper, rightOper, operator);//根据三个变量计算。如果/时右数为0,就抛异常.}catch(ArithmeticException ae) {
isExcp=true;if(leftOper==0)//左数,右数同时为0时.text=newStringBuilder("函数结果未定义。");elsetext=newStringBuilder("除数不能为零。");
}
rightOper=leftOper=result;//把得到的结果给左数,同时也给右数.text=newStringBuilder(String.valueOf(result));
isZero=true;
isRightInput=1;//直接就是1状态.不经过0}if(operator==0)//如果运算符没有.如:1+rightOper=leftOper=Double.parseDouble(number.toString());//左数和右数均赋值.//据cmd初始化operator.此步一定进行,不管是运算符功能还是=功能.if(cmd=="+")//很无奈的是不能用switch.enum太繁.operator=1;elseif(cmd=="-")
operator=2;elseif(cmd=="*")
operator=3;elseoperator=4;
isZero=true;
}//单目运算elseif(cmd=="sqrt") {if(isExcp)return;doublednum=Double.parseDouble(number.toString());if(dnum<0) {//如果当前数为负,就错误.isExcp=true;
text=newStringBuilder("函数输入无效。");
}else{
result=Math.sqrt(dnum);
number=text=newStringBuilder(String.valueOf(result));if(operator==0)//有运算符必赋值给右数.leftOper=result;else{
rightOper=result;
}
isZero=true;
}
}elseif(cmd=="%") {if(isExcp)return;doublednum=Double.parseDouble(number.toString());
result=leftOper*dnum/100;//这种规则让人很难适应,有点小变态.number=text=newStringBuilder(String.valueOf(result));if(operator==0)
leftOper=result;else{
rightOper=result;
}
isZero=true;
}elseif(cmd=="1/x") {if(isExcp)return;doublednum=Double.parseDouble(number.toString());if(dnum==0) {
isExcp=true;
text=newStringBuilder("除数不能为零。");
}else{
result=1/Double.parseDouble(number.toString());
number=text=newStringBuilder(String.valueOf(result));if(operator==0)
leftOper=result;else{
rightOper=result;
}
isZero=true;
}
}elseif(e.getActionCommand()=="=") {if(isExcp)return;doublednum=Double.parseDouble(number.toString());if(isRightInput==2) {//一次有效的右输入.如1+2=-2.如1+2=3=.就不响应3.rightOper=dnum;//当前数赋给右数.isRightInput=0;//=号破坏一次右输入,必须得以+-*/开头,后接数字}if(operator!=0) {//1+2=try{
result=Util.calculate(leftOper, rightOper, operator);
}catch(ArithmeticException ae) {
isExcp=true;if(leftOper==0)//左数,右数同时为0时.text=newStringBuilder("函数结果未定义。");elsetext=newStringBuilder("除数不能为零。");
}
leftOper=result;
}else//1=result=dnum;
text=newStringBuilder(String.valueOf(result));
isZero=true;
}elseif(e.getActionCommand()=="关于计算器") {
String temp="java模拟windows高模仿实用计算器.\n荞叶制作.qq:494053175 \n blog:sina wangflood";
JOptionPane.showMessageDialog(null, temp,"关于计算器",
JOptionPane.INFORMATION_MESSAGE);
}//BackSpace功能elseif(cmd=="Backspace") {if(isExcp)return;if((!isNeg&&number.length()<2)//正数剩一位时,负数剩二位时.直接跳到0||(isNeg&&number.length()<3)) {
isZero=true;
number=newStringBuilder("0");
}elsenumber=number.deleteCharAt(number.length()-1);//每次删除最后一位.text=number;
}elseif(cmd=="CE") {
isZero=true;
isExcp=false;//清异常.text=number;
}elseif(cmd=="C") {
operator=0;//清运算符.isZero=true;
leftOper=0;//清左数rightOper=0;//清右数.result=0;//清结果.number=text=newStringBuilder("0");//清当前数isExcp=false;//清异常isRightInput=0;//清一次有效右输入.}elseif(cmd=="MC") {if(isExcp)//同样也响应不了.异常的时候.return;
m=newStringBuilder("0");
}elseif(cmd=="MR") {//显示存储数到display.if(isExcp)return;
isRightInput=2;
number=text=m;
}elseif(cmd=="MS") {if(isExcp)return;
m=number;//将当前数赋给m.}elseif(cmd=="M+") {//当前数与m相加赋给mif(isExcp)return;
m=newStringBuilder(String.valueOf((Double.parseDouble(m
.toString())+Double.parseDouble(number.toString()))));
}else{//一般不给出现这种情况.我们都会上天堂的.System.out.println("欢迎来到地狱!");
}//按任何键都会触发的.tftext.setText(text.toString());if(m.length()!=0)//m不空的话就显示Mtfm.setText("M");elsetfm.setText("");if(isZero) {//为清空状态.浮点状态和负数状态回到默认.isFloat=0;
isNeg=false;
}
}privatevoidinitDisplay() {
tftext.setHorizontalAlignment(JTextField.RIGHT);
pdisplay.add(tftext);
tftext.setText("0.");
tfm.setHorizontalAlignment(JTextField.CENTER);
tfm.setEditable(false);
pm.add(tfm);
}privatevoidinitPbcm() {//生成按钮for(inti=0; i<27; i++) {
jb[i]=newJButton(strB[i]);
}for(inti=0; i<4; i++) {
jb[i].addActionListener(this);
pm.add(jb[i]);
}for(inti=4; i<7; i++) {
jb[i].addActionListener(this);
pc.add(jb[i]);
}for(inti=7; i<27; i++) {
jb[i].addActionListener(this);
pb.add(jb[i]);
}
pbc.add(pc, BorderLayout.NORTH);
pbc.add(pb, BorderLayout.CENTER);
pbcm.add(pm);
pbcm.add(pbc);
}privatevoidaddMenu() {this.setMenuBar(myMenuBar);//以下是编辑菜单项Menu editMenu=newMenu("编辑");
myMenuBar.add(editMenu);
MenuItem menuitemcopy=newMenuItem("复制");
MenuItem menuitemplaste=newMenuItem("粘贴");
MenuItem menuitemload=newMenuItem("用户登录");
editMenu.add(menuitemload);
editMenu.add(menuitemcopy);
editMenu.add(menuitemplaste);
menuitemload.addActionListener(this);
menuitemcopy.addActionListener(this);
menuitemplaste.addActionListener(this);//以下是编辑菜单项Menu watchMenu=newMenu("查看");
myMenuBar.add(watchMenu);
MenuItem menuitemstandard=newMenuItem("标准型");
MenuItem menuitemsencien=newMenuItem("科学型");
watchMenu.add(menuitemstandard);
watchMenu.add(menuitemsencien);
watchMenu.addSeparator();
watchMenu.add(newMenuItem("数字分组"));
menuitemstandard.addActionListener(this);
menuitemsencien.addActionListener(this);//以下是帮助菜单项Menu helpMenu=newMenu("帮助");
myMenuBar.add(helpMenu);
CheckboxMenuItem menuitemhelp=newCheckboxMenuItem("帮助主题",false);
MenuItem menuitemaboutcal=newMenuItem("关于计算器");
helpMenu.add(menuitemhelp);
helpMenu.addSeparator();
helpMenu.add(menuitemaboutcal);
menuitemhelp.addActionListener(this);
menuitemaboutcal.addActionListener(this);
}publicstaticvoidmain(String[] args) {newCal();
}
}