模拟windows10计算器的实现windows10模拟
用户界面部分:
import java.awt.*; import java.awt.event.*; import java.io.*; import java.util.HashMap; import java.util.Vector; import javax.swing.*; import javax.swing.border.Border; import javax.swing.table.*; public class caculate extends JFrame implements ActionListener,MouseListener { JTextField contain1,contain2;//内容显示区域 String midstring="";//用于需要计算表达式的更新 JComboBox sanjiao,hanshu;//三角学,函数下拉框 String resul[] =new String[100]; //存储用户点击的命令 int resulkey=0; //计数 String data[]=new String[100]; //存储按钮的内容 int data1[]=new int[] {16,17,18,21,22,23,26,27,28,31,32,33}; //要切换的按钮的位置 HashMap<String,String> map = new HashMap<>(); //存储命令的键值对 JButton pan1Button[]=new JButton[6]; //panel1按钮组 JButton pan2Button[]=new JButton[6]; //panel2按钮组 JButton pan3Button[]=new JButton[6]; static JButton button[]=new JButton[35]; Color color; Color color1=new Color(240,240,240); Color color2=new Color(230,230,230); Color color3=new Color(150,200,255); public static void main(String[] args) { // TODO Auto-generated method stub caculate cacu=new caculate(); cacu.setDefaultCloseOperation(DISPOSE_ON_CLOSE); cacu.setSize(340,545); cacu.setVisible(true); } public caculate() { super("计算器"); this.setBackground(color1); setLocationRelativeTo(getOwner()); setLayout(new GridBagLayout()); setMenuBar(change()); map.put("+","+"); map.put("-","-"); map.put("*","*"); map.put("/","/"); map.put("(","("); map.put(")",")"); map.put("x^2","^"); map.put("x^3","^"); map.put("1/x","^"); map.put("e^x","^"); map.put("√x","^"); map.put("x^y","^"); map.put("10^x","^"); map.put("∛x","^"); map.put("√(y&x)","^"); map.put("2^x","^"); map.put("n!","#"); map.put("|x|","a"); map.put("exp","e"); map.put("mod","%"); map.put("log_yx","l"); map.put("log","l"); map.put("ln","l"); map.put("+/-","~"); map.put("sin","s"); map.put("sin^-1","S"); map.put("sinh","h"); map.put("cos","c"); map.put("cos^-1","C"); map.put("cosh","H"); map.put("tan","t"); map.put("tan^-1","T"); map.put("tanh","N"); map.put("rand","r"); map.put("ceil","q"); map.put("floor","f"); map.put("pi","p"); map.put("e","E"); map.put(".", "."); contain1=new JTextField(10); contain1.setBorder(BorderFactory.createEmptyBorder()); contain1.setHorizontalAlignment(JTextField.RIGHT); contain1.setEditable(false); contain1.setBackground(color1); contain2=new JTextField(10); contain2.setText("0"); contain2.setBorder(BorderFactory.createEmptyBorder()); contain2.setHorizontalAlignment(JTextField.RIGHT); contain2.setBackground(color1); contain2.setFont(new Font("楷体",Font.BOLD,32)); GridBagConstraints gridBag=new GridBagConstraints(); gridBag.fill=GridBagConstraints.BOTH; gridBag.weightx=100; gridBag.weighty=10; addToBag(contain1,gridBag, 0,0,1,1); addToBag(contain2,gridBag, 0,1,1,1); gridBag.weightx=100; gridBag.weighty=0; JPanel pan1=new JPanel(); JPanel pan2=new JPanel(); JPanel pan3=new JPanel(); pan1.setBackground(color1); pan1.setLayout(new GridLayout(1,6,0,0)); pan2.setBackground(color1); pan2.setLayout(new GridLayout(1,6,0,0)); pan3.setBackground(color1); pan3.setLayout(new GridLayout(1,6,0,0)); addToBag(pan1,gridBag,0,2,1,1); addToBag(pan2,gridBag,0,3,1,1); addToBag(pan3,gridBag,0,4,1,1); String[] san= {"三角学","sin","cos","tan","sin^-1","cos^-1","tan^-1","sinh","cosh","tanh"}; sanjiao=detCbB(san); pan3.add(sanjiao); String[] han= {"函数","ceil","floor","rand"}; hanshu=detCbB(han); pan3.add(hanshu); JPanel pan=new JPanel(); pan.setBackground(color1); pan.setLayout(new GridLayout(7,5,0,0)); gridBag.weightx=100; gridBag.weighty=100; addToBag(pan,gridBag,0,5,1,1); getkey(data); //从文件中读取按钮数据 Initpan(data,pan);//初始化pan面板 Initpan1(data,pan1);//初始化pan1面板 Initpan2(data,pan2);//初始化pan2面板 } void Initpan(String[] data,JPanel pan) { int j=0; for(int i=0;i<35;i++) { button[i]=new JButton(data[j++]); button[i].setBackground(color1); button[i].setBorder(BorderFactory.createMatteBorder(1, 1, 1, 1, color2)); pan.add(button[i]); button[i].addActionListener(this); button[i].addMouseListener(this); } for(int x:data1) { button[x].setBackground(Color.white); } button[34].setBackground(color3); } void Initpan1(String[] data ,JPanel pan1) { int j=41; for(int i=0;i<5;i++) { if(i<2) { pan1Button[i]=new JButton(data[j++]); pan1Button[i].addActionListener(this); pan1Button[i].addMouseListener(this); } else { pan1Button[i]=new JButton(" "); } pan1Button[i].setBackground(color1); pan1Button[i].setBorderPainted(false); pan1.add(pan1Button[i]); } } void Initpan2(String[] data,JPanel pan2) { int j=43; for(int i=0;i<6;i++) { pan2Button[i]=new JButton(data[j++]); pan2Button[i].setBackground(color1); pan2Button[i].setBorderPainted(false); pan2.add(pan2Button[i]); if(i<2||i==5) { pan2Button[i].setEnabled(false); } else { pan2Button[i].addActionListener(this); pan2Button[i].addMouseListener(this); } } } void addToBag(Component c,GridBagConstraints gbc, int x,int y,int w,int h) { gbc.gridx=x; gbc.gridy=y; gbc.gridheight=h; gbc.gridwidth=w; add(c,gbc); } //从文件中读取数据 public void getkey(String[] param) { try { File file=new File("text.txt"); BufferedReader in=new BufferedReader(new InputStreamReader(new FileInputStream(file),"UTF8")); boolean eof=false; int flag=0; while(!eof) { String x=in.readLine(); if(x==null) { eof=true; } else { param[flag++]=x; } } } catch(IOException e) {} } //创建下拉组合框 public JComboBox detCbB(String[] Ordata) { JComboBox example=new JComboBox(Ordata); example.setBackground(color1); example.setBorder(null); //example.setForeground(color); example.addItemListener(new ItemListener() { @Override public void itemStateChanged(ItemEvent e) { // TODO Auto-generated method stub if(e.getStateChange()==ItemEvent.SELECTED) { if(midstring.equals("=")) { contain1.setText(""); midstring=""; } if(e.getStateChange()==ItemEvent.DESELECTED) { } int k=example.getSelectedIndex(); if(Ordata[k]=="三角学"||Ordata[k]=="函数") { } else { resul[resulkey++]=Ordata[k]; midstring+=Ordata[k]; contain1.setText(midstring); } } } }); return example; } @Override public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub String command=e.getActionCommand(); sanjiao.setSelectedIndex(0); hanshu.setSelectedIndex(0); if(midstring.equals("=")) { contain1.setText(""); midstring=""; } if(command.equals("2nd")) { JButton butt=(JButton)e.getSource(); if(butt.getBackground()==color3) { restoreButton(); butt.setBackground(color1); color=color1; } else { changeButton(); butt.setBackground(color3); color=color3; } } else { if(command.equals("=")) { String result=changeType(resul); System.out.println(result); System.out.println(resulkey); System.out.println(Cauculate.midtolast(result)); Double result1=Cauculate.CaculateLastStackExpression(Cauculate.midtolast(result)); contain2.setText(Double.toString(result1)); midstring="="; resulkey=0; } else { if(command.equals("c"))//清除单个命令 { if(midstring.length()>0) { int len=resul[resulkey-1].length();//获取上一个命令的长度 midstring=midstring.substring(0, midstring.length()-len); //有问题 resulkey--; } command=""; } if(command.equals("×")) //清除所有的命令 { midstring=""; command=""; resulkey=0; } resul[resulkey++]=command; midstring+=command; if(command=="") {//纠正计数问题 resulkey--; } contain1.setText(midstring); if(command.charAt(0)>'0'&&command.charAt(0)<'9') { contain2.setText(command); } } } } private String changeType(String[] resul2) { // TODO Auto-generated method stub String ch=""; for(int i=0;i<resulkey;i++) { if(!isNumber(resul2[i])) { switch (resul2[i]) { case "x^2": ch+=map.get(resul2[i])+"2"; break; case "x^3": ch+=map.get(resul2[i])+"3"; break; case "1/x": ch+=map.get(resul2[i])+"(0-1)"; break; case "e^x": ch+='E'+map.get(resul2[i]); break; case "√x": ch+=map.get(resul2[i])+"(1/2)"; break; case "x^y": ch+=resul2[i+1]+map.get(resul2[i])+resul2[i+2]; i+=2; break; case "10^x": ch+="10"+map.get(resul2[i]); break; case "∛x": ch+=map.get(resul2[i])+"(1/3)"; break; case "√(y&x)": ch+=resul2[i+1]+map.get(resul2[i])+(1/(Double.parseDouble(resul2[i+2]))); i+=2; break; case "log_yx": ch+=resul2[i+1]+map.get(resul2[i])+resul2[i+2]; i+=2; break; case "log": ch+="10"+map.get(resul2[i]); break; case "ln": ch+="E"+map.get(resul2[i]); break; default: ch+=map.get(resul2[i]); break; } } else { ch+=resul2[i]; } } return ch; } public static boolean isNumber(String str) { for(int i=0;i<str.length();i++) { if(!Character.isDigit(str.charAt(i))) { return false; } } return true; } private MenuBar change() { MenuBar jmenubar=new MenuBar(); jmenubar.addNotify(); Menu ch=new Menu("=="); jmenubar.add(ch); MenuItem item1=new MenuItem("Science"); ch.add(item1); MenuItem item2=new MenuItem("绘图"); ch.add(item2); MenuItem item3=new MenuItem("标准"); ch.add(item3); MenuItem item4=new MenuItem("程序员"); ch.add(item4); Menu type=new Menu("Science"); jmenubar.add(type); return jmenubar; } //按2nd改变按钮 public void changeButton() { int k=5; for(int i=35;i<41;i++) { button[k].setText(data[i]); k+=5; } } //按2nd复原按钮 public void restoreButton() { int k=5; for(int i=35;i<41;i++) { button[k].setText(data[k]); k+=5; } } @Override public void mouseClicked(MouseEvent e) { // TODO Auto-generated method stub } @Override public void mousePressed(MouseEvent e) { // TODO Auto-generated method stub } @Override public void mouseReleased(MouseEvent e) { // TODO Auto-generated method stub } @Override public void mouseEntered(MouseEvent e) { // TODO Auto-generated method stub if(e.getComponent().getClass().equals(button[0].getClass())) { color=((JButton)e.getSource()).getBackground(); ((JButton)e.getSource()).setBackground(new Color(220,220,220)); } } @Override public void mouseExited(MouseEvent e) { // TODO Auto-generated method stub if(e.getComponent().getClass().equals(button[0].getClass())) { ((JButton)e.getSource()).setBackground(color); } } }表达式计算部分:
基本原理
将获得的表达式由中缀转化为后缀,利用java的栈进行相应的运算。
package tttt; import java.util.*; public class Cauculate { //创建用于匹配运算符的字符数组 private static char[] trans1= {'+','-','*','/','#','^','a','e','%','l','~','s','S','h','H','c','C','t','T','N','r','q','f'};//总数组 private static char[] trans2= {'+','-','*','/','^','e','%','l'};//单目运算符 private static char[] trans3= {'a','#','~','s','S','h','H','c','C','t','T','N','q','f'};//双目运算符 public static int transExp(char exp) {//运算符优先级 int re = 0; switch (exp) { case '*': case '/': re = 2; break; case '+': case '-': re = 1; break; case '^': re = 4; break; case '#': case 'l': case '~': case 'e': case 's': case 'S': case 'h': case 'c': case 'C': case 'H': case 't': case 'T': case 'N': case 'a': case 'q': case 'f': case 'r': case '%': re=3; break; } return re; } public static String midtolast(String mid){//中缀表达式转后缀表达式 Stack<Character>OperateorStack=new Stack<Character>(); Stack<String>LastStack=new Stack<String>();//后缀表达式栈; int length=mid.length(); int index=0;//指向String扫描的当前位置; char element;// String num="";// while(index<length){//扫描整个mid element=mid.charAt(index); if(element>='0'&&element<='9'){//得到一整个数据,例如'123' num=num+element; if(index==length-1) { LastStack.push(num); } else { char ch=mid.charAt(index+1); if(ch=='.') { num+=ch; index++; } else { if(ch<'0'||ch>'9') { LastStack.push(num); num=""; } } } } else if(element=='E') { LastStack.push(Double.toString(Math.E)); } else if(element=='p') { LastStack.push(Double.toString(Math.PI)); } else if(element=='('){ OperateorStack.push(element); } else if(element==')'){ while(OperateorStack.peek()!='('){ LastStack.push(OperateorStack.pop().toString());//将左括号到右括号之间的操作符弹出 } OperateorStack.pop();//让左括号出栈 } else if(castele(element,trans1)){ if(OperateorStack.isEmpty()||OperateorStack.peek()=='('){//栈为空或栈顶元素为'('则直接入栈 OperateorStack.push(element); } else if(transExp(element)>transExp(OperateorStack.peek())){ OperateorStack.push(element); }//如果element的优先级高于栈顶元素则直接入栈 else if(transExp(element)<=transExp(OperateorStack.peek())){ while(!OperateorStack.isEmpty()&&OperateorStack.peek()!='('){ LastStack.push(OperateorStack.peek().toString()); OperateorStack.pop(); if(!OperateorStack.isEmpty()&&transExp(element)<=transExp(OperateorStack.peek())) { continue; } else { break; } } OperateorStack.push(element); }//如果element的优先级低于或等于栈顶元素等于栈顶元素则将栈顶元素加入后缀表达栈中 } index++; } while(!OperateorStack.isEmpty()){ LastStack.push(OperateorStack.pop().toString()); } String LastStackExpression=LastStack.pop(); while(!LastStack.isEmpty()){ LastStackExpression=LastStack.pop()+" "+LastStackExpression; } return LastStackExpression; } public static double CaculateLastStackExpression(String LastStackExpression){ Stack<Double>operandStack=new Stack<Double>();//初始化一个操作数栈 String[] elements=LastStackExpression.split(" ");//将LastStackExpression以空格分隔开; String element=null;//后缀表达式扫描到的单元; char elementHead; double operand=0,operand1=0,operand2=0; for (int i = 0; i < elements.length; i++) {//依次扫描后缀表达式的单元 element=elements[i]; elementHead=element.charAt(0); if (elementHead>='0'&&elementHead<='9') {//如果扫描到的是操作数串,将其转换为double数据,并压入操作数栈 operand=Double.parseDouble(element); operandStack.push(operand); }else if(castele(elementHead,trans2)){//如果扫描到的是运算符 operand1=operandStack.pop();//取操作数栈的栈顶 operand2=operandStack.pop();//取操作数栈的栈顶 operand=caculateResult(operand1,operand2,elementHead);//进行运算,得出返回结果 operandStack.push(operand);//将结果压入操作数栈 } else if(castele(elementHead,trans3)) { operand1=operandStack.pop(); operand=caculateResult(operand1,0.0,elementHead); operandStack.push(operand); } else if (elementHead=='r') { operand=caculateResult(0.0,0.0,elementHead); operandStack.push(operand); } } return operandStack.pop() ; } public static double caculateResult(double operand1,double operand2,char operator){//返回的运算结果 double result=0; switch (operator) { case '+': result=operand1+operand2; break; case '-': result=operand2-operand1; break; case '*': result=operand1*operand2; break; case '/': result=operand2/operand1; break; case '^': result=ScientificCalculator.Pow2(operand2,operand1); break; case '#': result=ScientificCalculator.Factorial((int)operand1); break; case 'l': result=ScientificCalculator.Log(operand2,operand1); break; case '~': result=ScientificCalculator.Reverse(operand1); break; case 'e': result=ScientificCalculator.Exp(operand2,(int)operand1); break; case 's': result=ScientificCalculator.Sin(operand1,1); break; case 'S': result=ScientificCalculator.Sin(operand1,2); break; case 'h': result=ScientificCalculator.Sin(operand1,3); break; case 'c': result=ScientificCalculator.Cos(operand1,1); break; case 'C': result=ScientificCalculator.Cos(operand1,2); break; case 'H': result=ScientificCalculator.Cos(operand1,3); break; case 't': result=ScientificCalculator.Tan(operand1,1); break; case 'T': result=ScientificCalculator.Tan(operand1,2); break; case 'N': result=ScientificCalculator.Tan(operand1,3); break; case 'a': result=ScientificCalculator.abs(operand1); break; case 'q': result=ScientificCalculator.ceil(operand1); break; case 'f': result=ScientificCalculator.floor(operand1); break; case 'r': result=ScientificCalculator.rand(); break; case '%': result=ScientificCalculator.Mod(operand2,operand1); break; default: break; } return result; } //判断符号 public static boolean castele(char element,char[] Su) { for(char x:Su) { if(element==x) return true; } return false; } }单个函数部分:
单个按钮功能的实现。
package tttt; import java.lang.Math; import java.util.HashMap; import java.util.Map; public class ScientificCalculator { // 指数运算:x^2,1/x,e^x,平方根 " ^ " static public double Pow2(double x,double n) { return Math.pow(x,n); } // 阶乘运算: " # " static public int Factorial(int x) { if (x <= 0) { throw new IllegalArgumentException("需要计算的参数必须为正数!");//抛出不合理参数异常 } if (x == 1) { return 1;//跳出循环 } else { return x * Factorial(x - 1);//递归 } } // 对数运算:log,ln “ l ” static public double Log(double base,double value) { return Math.log(value) / Math.log(base); } static public double Mod(double x,double y) { return x%y; } // 取反运算:+/- " ~ " static public double Reverse(double x) { return -x; } // 科学计数法:x*e^n "e" static public double Exp(double x,int n) { return x * Math.pow(10,n); } // sin、sin^-1(asin)、sinh、sinh^-1(asinh) // 运算: degree:度数; sin:flag=1 " s "; sin^-1(asin):flag=2 " S "; sinh:flag=3 " h " static public double Sin(double degree,int flag) { double radians = Math.toRadians(degree); switch (flag) { case 1: return Math.sin(radians); case 2: return Math.asin(radians); case 3: return Math.sinh(degree); default: throw new IllegalStateException("Unexpected value: " + flag); } } // cos、cos^-1(acos)、cosh // 运算: degree:度数; cos:flag=1 " c "; cos^-1(acos):flag=2 " C "; cosh:flag=3 " H " static public double Cos(double degree,int flag) { double radians = Math.toRadians(degree); switch (flag) { case 1: return Math.cos(radians); case 2: return Math.acos(radians); case 3: return Math.cosh(degree); default: throw new IllegalStateException("Unexpected value: " + flag); } } // tan、tan^-1(atan)、tanh // 运算: degree:度数; tan:flag=1 " t "; tan^-1(atan):flag=2 " T "; tanh:fla g=3 " N " static public double Tan(double degree,int flag) { double radians = Math.toRadians(degree); switch (flag) { case 1: return Math.tan(radians); case 2: return Math.atan(radians); case 3: return Math.tanh(degree); default: throw new IllegalStateException("Unexpected value: " + flag); } } // 绝对值:|x| " a " static public double abs(double x) { return Math.abs(x); } // 向上取整:ceil " q " static public double ceil(double x) { return Math.ceil(x); } // 向下取整:floor " f " static public double floor(double x) { return Math.floor(x); } // 取随机数:rand " r " static public double rand() { return Math.random(); } public static void main(String[] args) { System.out.println(Exp(Math.PI,1)); } }