Java GUI带括号的计算器(支持小数)

package Caculator;
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Color;
import java.awt.Frame;
import java.awt.GridLayout;
import java.awt.Panel;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.math.BigDecimal;
import java.math.MathContext;

import javax.swing.JFrame;
import com.sun.glass.events.WindowEvent;

public class MyCalculator {
       public static void main(String[] args) {
           new MyCalculator().launch();
                                              }

public boolean result=false;//输入#之后result变为真,此时可以计算结果了,用于判断能否进行计算。
public boolean end=false;//前面有内容的时候才将其变为true,且输入#之后什么都不能输入了。
/**   
 * 首先对这几个boolean变量进行具体阐述:rusult只有在#(结束符)输入之后才会赋为true,也就是说只有输入#之后才能输入==;
 * end用于#(结束符)能否进行输入,#前必须为正确的式子,故#的前一位只能是数字或者右括号。
 * 
 * 分为以下几种:数字,算数符(+ - * /),左括号,右括号,点,清零符
 * 数字任何时候均可进行输入
 * judge1用于运算符的判断,运算符之前只能有数字,括号
 * judge2用于点的判断。
 * judgeleft用于左括号的判定,另外只有在输入左括号之后才能输入右括号,另外输完左括号之后还能再输,可以连续输入两个左括号
 * judgeleftright 用于右括号的判定,另外输完右括号之后还能再输,可以连续输入两个右括号
 * 其中还有一些情况没有完全避免
 *    
 */
public boolean judge1=false;
public boolean judge2=true;
public boolean judgeleft=true;
public boolean judgeleftright=false;
     public void launch()                                                  {
        
        TextField tf=new TextField(30);
        tf.setSize(300, 100);
        tf.setBackground(Color.WHITE);
        tf.setEditable(true);
        JFrame interface1=new JFrame();
        interface1.setTitle("按#=得结果");
        interface1. setLayout(new BorderLayout());//创建BorderLayout布局(几行几列)
        interface1.add(tf,BorderLayout.NORTH);
        Panel p=new Panel(new GridLayout(5,4,5,5));//将面板设置成5行四列
        for(int i=0;i<10;i++)
        {
            Button bn=new Button(""+i);
            bn.setActionCommand("数字");//数字为一类
            p.add(bn);
            bn.addActionListener(new ActionEventDemo(interface1,tf));
         }
         Button D=new Button(".");
         D.setActionCommand("点");
         p.add(D);
         D.addActionListener(new ActionEventDemo(interface1,tf));//点为一类
         
         
         
         Button add=new Button("+");
         add.setActionCommand("算数符");
         p.add(add);
         add.addActionListener(new ActionEventDemo(interface1,tf));
        
         Button sub=new Button("-");
         sub.setActionCommand("算数符");
         p.add(sub);
         sub.addActionListener(new ActionEventDemo(interface1,tf));
         
         Button mult=new Button("*");
         mult.setActionCommand("算数符");
         p.add(mult);
         mult.addActionListener(new ActionEventDemo(interface1,tf));
         
         Button div=new Button("/");
         div.setActionCommand("算数符");
         p.add(div);
         div.addActionListener(new ActionEventDemo(interface1,tf));//运算符为一类
         
         
         Button left=new Button("(");
         left.setActionCommand("左括号");
         p.add(left);
         left.addActionListener(new ActionEventDemo(interface1,tf));
        
         Button right=new Button(")");
         right.setActionCommand("右括号");
         p.add(right);
         right.addActionListener(new ActionEventDemo(interface1,tf));//括号为一类
         
         Button end=new Button("#");
         end.setActionCommand("结束符");
         p.add(end);
         end.addActionListener(new ActionEventDemo(interface1,tf));//结束符
         
         Button result=new Button("==");
         result.setActionCommand("结果符");
         p.add(result);
         result.addActionListener(new ActionEventDemo(interface1,tf));//按完结束符才能按结果符
         
         Button zero =new Button("清零");
         zero.setActionCommand("清零符");
         p.add(zero);
         zero.addActionListener(new ActionEventDemo(interface1,tf));
         
         interface1.add(p,BorderLayout.CENTER);
         interface1.setBounds(300,300,400,400);
         interface1.setBackground(Color.black);
         interface1. setVisible(true);
         interface1.addWindowListener(new WindowAdapter() {
             public void windowClosing(WindowEvent e) {
                 System.exit(-1);
                                                      }
                                               }
                            );
                                                                       }
     
     
     
class ActionEventDemo implements ActionListener                             {
    JFrame interface1=new JFrame();
    TextField tf=new TextField();
    ActionEventDemo(JFrame interface1,TextField tf){
        this.interface1=interface1;
        this.tf=tf;
                                                    }
    public void actionPerformed(ActionEvent e)                                                          {
     String strAc=e.getActionCommand();//*得到按钮实际命令。
     Button bn=(Button)e.getSource();
     String strLb=bn.getLabel();//得到按钮标签
     
     
     
     if(strAc.equals("数字")) {
         tf.setText(tf.getText()+strLb);
         judge1=true;//输入数字之后就可以输算数符+ - * /了
         
         end=true;//可以上输入结束符了,#符号之前只能是数字或者右括号
         
         judgeleft=true;
                              }
     
     else if(strAc.equals("算数符")&&judge1) {//运算符是一种
         tf.setText(tf.getText()+strLb);
         judge1=false; 
         judge2=true; 
         
         end=false;
    
         judgeleft=true;
         
                                         }
     
     else if(strAc.equals("左括号")&&judgeleft) {//左括号是一种
         tf.setText(tf.getText()+strLb);
         judgeleftright=true;//可以输入右括号了
         
         end=false;//#符号之前只能是数字或者右括号
                                                }
     
     else if(strAc.equals("右括号")&&judgeleftright) {//右括号是一种
         tf.setText(tf.getText()+strLb);
         //judgeleftright=false;
         
         judgeleft=true;
         
         end=true;
                                                    }
     

     else if(strAc.equals("点")&&judge2)            {//点是一种
         tf.setText(tf.getText()+strLb);
         judge2=false;
         
         judgeleft=false;
         
         end=false;
         
                                                   }
     
     
     
     else if(strAc.equals("清零符"))                  {
         tf.setText("");
         //boolean变量全部赋成初值
         result=false;//输入#之后result变为真,此时可以计算结果了,用于判断能否进行计算。
         end=false;//前面有内容的时候才将其变为true,且输入#之后什么都不能输入了。

         judge1=false;
         judge2=true;
         judgeleft=true;
         judgeleftright=false;
        
                                                    }
     
     
     else if(strAc.equals("结束符")&&end)         {
         tf.setText(tf.getText()+strLb);
         
           result=true;
         
         //什么都没法输入了,表示已经结束运算
           end=false;
           judge1=false;
           judge2=false;
           judgeleft=false;
           judgeleftright=false;
         
                                                 }
     
     
     else if(strAc.equals("结果符")&&result)        {
         String string=tf.getText();//得到结果符,获得TextField标签上内容字符串
         MyCaculate caculate=new MyCaculate ();//形成计算的类的对象
     
      double end1=caculate.caculate(tf.getText());//通过caculate方法得到计算结果end1
      BigDecimal bg = new BigDecimal(end1);
      double f1 = bg.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
         tf.setText(String.valueOf(f1)+"");
    
                                                  }
     
                                                                                                         }
                                                                               }
}
            
    
                                                                                                           
                                                                                   

                                                                              

                                         




package Caculator;

import java.util.Stack;
/**   
 * 利用栈,进行四则运算的类   
 * 用两个栈来实现算符优先,一个栈用来保存需要计算的数据numStack,一个用来保存计算优先符priStack   
 *    
 *  基本算法实现思路为:用当前取得的运算符与priStack栈顶运算符比较优先级:若高于,则因为会先运算,放入栈顶;   
 *  若等于,因为出现在后面,所以会后计算,所以栈顶元素出栈,取出操作数运算;   
 *  若小于,则同理,取出栈顶元素运算,将结果入操作数栈。各个优先级'(' > '*' = '/' > '+' = '-' > ')'   
 *    
 */      
public class MyCaculate {
        Stack<Double> numStack = new Stack<Double>();;// 操作数栈        
        Stack<Character> priStack = new Stack<Character>();// 操作符栈      //放在最前面,在方法中用不了
    public double caculate(String numStr1)                                       {
            String numStr=numStr1.substring(0, numStr1.length()-1);//由于设置原因GUI界面传入的字符串最后一个字符为#,把它去掉,不去掉也行,那就把#作为结束符
            if (numStr.length() > 1 && !"=".equals(numStr.charAt(numStr.length() - 1) )) {
                numStr += "=";
            //=作为结束符                                                                 
                                                                                         }
         
            StringBuffer temp=new StringBuffer();//为提高效率,临时存放字符
            int i=0;
            for(i=0;i<numStr.length();i++) {//大循环
                
                char ch=numStr.charAt(i);
                if(isNumber(ch)) temp.append(ch);
                else  {
                    //转换成String类型
                    if(!"".equals(temp.toString())) {//它是符号了说明符号前面的数字切割完毕
                        double num=Double.parseDouble(temp.toString());
                        numStack.push(num);
                        temp.delete(0, temp.length());//temp存放临时结果,放入栈中.
                                                     }
                    
  // 用当前取得的运算符与栈顶运算符比较优先级:若高于,则因为会先运算,放入栈顶;若等于,因为出现在后面,所以会后计算,所以栈顶元素出栈,取出操作数运算;      
  // 若小于,则同理,取出栈顶元素运算,将结果入操作数栈。      
  // 判断当前运算符与栈顶元素优先级,取出元素,进行计算(因为优先级可能小于栈顶元素,还小于第二个元素等等,需要用循环判断)      
                    while(!compare(ch)&&!priStack.empty()) {//不如栈顶元素优先级高,那么我们将栈顶运算符取出,进行运算即可。
                        double b=numStack.pop();
                        double a=numStack.pop();
                        double c;
                        switch((char)priStack.pop()) {
                        case '+':c=a+b; numStack.push(c); break;
                        case '-':c=a-b; numStack.push(c);break;
                        case '*':c=a*b;numStack.push(c);break;
                        case '/':c=a/b;numStack.push(c);break;
                                                      }
                                                              }
                     if(ch!='=')   {priStack.push(new Character(ch));
                     if(ch==')') {// 当栈顶为'(',而当前元素为')'时,则是括号内以算完,去掉括号      
                         priStack.pop();
                         priStack.pop();
                                 }
                                    }
                       }
                                             }
            return numStack.pop();    
                                                                               }
    
    
    private boolean isNumber(char num) {
        if (num >= '0' && num <= '9'||num=='.') return true;
        else return false;//有了这个方法就不用判断他是否是数字还是符号了,如果是.也把它当作数字来看待
                                        }
    
 /**   
  * 比较当前操作符与栈顶元素操作符优先级,如果比栈顶元素优先级高,即最后算,则返回true,否则返回false   
  *    
  *  str 需要进行比较的字符   
  *  比较结果 true代表比栈顶元素优先级高,false代表比栈顶元素优先级低  ,true表示后算 
 */         
    public boolean compare(char str) {      
        if (priStack.empty()) {      
            // 当为空时,显然 当前优先级最低,返回高
            return true;      
                              }      
        char last = (char) priStack.lastElement();      
        // 如果栈顶为'('显然,优先级最低,')'不可能为栈顶。      
        if (last == '(') {  //'('为栈顶无法放入其他符号,直到遇到右括号出栈,入栈
            return true;      
                         }      
        switch (str) {      
        // '+-'为最低,一直返回false,先算,出栈
        case '+':      
            return false;    
        case '-':      
            return false;      
        case '(':      
            // '('优先级最高,显然返回true,最后算,入栈    
            return true;      
        case '=':      
            return false;// 结束符 ,全部出栈
        case ')':      
            // ')'优先级最低,前面必有左括号,出栈   
            return false;      
        case '*': {      
             
            if (last == '+' || last == '-')     //入栈 
                return true;      
            else      
                return false;      //栈顶元素出栈
        }      
        case '/': {      
            if (last == '+' || last == '-')      
                return true; //入栈     
            else      
                return false;     //栈顶元素出栈 
        }      
        }      
        return true;      
                                   }      
    
         //public static void main(String []args) {
             // MyCaculate operate = new MyCaculate();      
             // double t = operate.caculate("((9.8-3.5)/(25.1-25.3)+7)*4#");        
               // System.out.println(t);   
                                              //  }//用于测试数据
}

猜你喜欢

转载自www.cnblogs.com/lyd66-/p/12127686.html
今日推荐