【Java】Java使用Swing实现一个模拟计算器(有源码)

今天翻了翻之前写的代码,发现自己之前还写了一个计算器,今天把我之前写的代码分享出来。

我记得那会儿刚学不会写,写的乱七八糟,但拿来当期末作业还是不错的哈哈。

直接上源码,后上讲解。

一、源码

代码语言:javascript
复制
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.text.DecimalFormat;
import java.util.function.ToDoubleBiFunction;

public class MyCalculator {
private JFrame frame=new JFrame("CSDN--哈__");
private String[] keys = {"%","C","CE","Back","1⁄x","X²","√x","÷","7","8","9",
"X","4","5","6","-","1","2","3","+","+/-","0",".","="};//计算器的功能键保存
private JButton [] buttons=new JButton[keys.length];//创建按钮
private JTextField resultText=new JTextField("0");//结果保存用于在计算器上显示
private double resultNum =0.0000;//用于保存运算的结果

private boolean firstDigit=true;//判断是否是第一个输入的数字,或者是运算符后第一个数字
private String operate ="=";//记录当前的运算符
private boolean opearteValidFlag =true;//判断当前输入是否合法



//构造函数
public MyCalculator(){
    frame.setLocation(300,200);
    frame.setSize(new Dimension(366,439));
    frame.setVisible(true);
    frame.setResizable(true);//窗口大小可修改
    //这里采用awt组件来关闭窗口  事件监听
    frame.addWindowListener(new WindowAdapter() {
        @Override
        public void windowClosed(WindowEvent e) {
            System.exit(0);
        }
    });
}

public void init(){
    //先定义三种颜色 用于背景板的填充  数值为网上查找
    Color c1=new Color(181,181,181);
    Color c2=new Color(126,192,238);
    Color c3=new Color(232,232,232);
    //计算器功能面板初始化
    JPanel pText =new JPanel();//用于保存文本域
    JPanel pKey =new JPanel();//用于保存功能按键
    //对文本域进行初始化
    pText.setLayout(new BorderLayout());
    pText.add(resultText);
    resultText.setFont(new Font("楷体",Font.BOLD,43));//设置文本框中字体的格式
    resultText.setHorizontalAlignment(JTextField.RIGHT);//文本框默认右对齐
    resultText.setEditable(false);//文本域不可编辑
    resultText.setBorder(null);//设置边框为无
    resultText.setBackground(c1);
    //对功能案件进行初始化
    pKey.setLayout(new GridLayout(6,4,2,2)); //六行四列,相邻两个按钮上下间隔均为两个像素
    //开始在按键区加入前八个功能键
    for (int i = 0; i < 8; i++) {
        buttons[i]=new JButton(keys[i]);
        pKey.add(buttons[i]);
        buttons[i].setBackground(c3);
        buttons[i].setForeground(Color.BLACK);
        buttons[i].setFont(new Font(Font.SERIF,Font.PLAIN,18));
        buttons[i].setBorderPainted(false);//设置无边框
        buttons[i].addActionListener(myActionListener);//添加监听器
    }
    for (int i = 8; i < keys.length; i++) {
        buttons[i]=new JButton(keys[i]);
        pKey.add(buttons[i]);
        if((i+1)%4==0)  buttons[i].setBackground(c3);
        else buttons[i].setBackground(Color.white);
        buttons[i].setForeground(Color.BLACK);
        buttons[i].setFont(new Font(Font.SERIF,Font.PLAIN,18));
        buttons[i].setBorderPainted(false);//设置无边框
        buttons[i].addActionListener(myActionListener);//添加监听器
    }
    //最后将=号的背景色改为蓝色,也就是c2
    buttons[keys.length-1].setBackground(c2);
    pKey.setBackground(c1);

    frame.add(pText,BorderLayout.NORTH);
    frame.add(pKey);
   /* pText.setBorder(BorderFactory.createMatteBorder(25,3,1,3,c1));
    pKey.setBorder(BorderFactory.createMatteBorder(6,3,3,3,c1));*/
}
public class MyActionListener implements ActionListener{
    @Override
    public void actionPerformed(ActionEvent e) {
        String key = e.getActionCommand();
        //对于具有清除删除功能按键的处理(CE C BACK)
        if(key.equals(keys[1])||key.equals(keys[2])||key.equals(keys[3])){
            doDeleteKey(key);
        }
        //对只需要一个数值的按键处理(% 1/x x² √x  +/-  )
        else if(key.equals(keys[0])||key.equals(keys[4])||key.equals(keys[5])||key.equals(keys[6])||
                key.equals(keys[20])){
            doOperator1(key);

        }
        //对需要两个数值的按键的处理(÷ X - += )
        else if(key.equals(keys[7])||key.equals(keys[11])||key.equals(keys[15])||key.equals(keys[19])||
                key.equals(keys[23])){
            doOperator2(key);
        }
        //对数字按键进行处理(1 2 3 4 5 6 7 8 9 .)
        else{
            doNumberKey(key);
        }
    }
}
private void doDeleteKey(String key){
    if(key.equals("CE")){
        resultText.setText("0");
    }
    else if(key.equals("C")){
        resultText.setText("0");
        resultNum=0.0000;
        firstDigit=true;
        opearteValidFlag=true;
        operate="=";
    }
    else{
        String text=resultText.getText();
        if(text.length()>1){
            resultText.setText(text.substring(0,text.length()-1)); //如果内容长度大于1,那么直接删掉最后一个字符
        }else{
            //内容长度等于1
            resultText.setText("0");
            firstDigit=true;
        }
    }
}
private void doOperator1(String key){
    //对只需要一个数值的按键处理(% 1/x x² √x  +/-  )
    operate=key;
    if(operate.equals("%")){
        resultNum=getNumFromText()/100;
    }
    else if(operate.equals("1⁄x")){
        if(getNumFromText()==0){
            //System.out.println("0没有倒数!");
            resultText.setText("零没有倒数!");
            opearteValidFlag=false;
        }else{
            resultNum=resultNum+1.0/getNumFromText();
        }
    }
    else if(operate.equals("√x")){
        if(getNumFromText()<0){
            //System.out.println("负数不能开方!");
            resultText.setText("负数不能开方!");
            opearteValidFlag=false;
        }else{
            resultNum=resultNum+Math.sqrt(getNumFromText());
        }
    }
    else if(operate.equals("X²")){

        resultNum=resultNum+getNumFromText()*getNumFromText();
    }
    else if(key.equals("+/-")){
        resultNum=-getNumFromText();
        firstDigit=true;
        opearteValidFlag=true;
    }
}
//两个数进行运算 ÷ X - + =
private void doOperator2(String key){
    if(operate.equals("÷")){
        if(getNumFromText()==0){
            //System.out.println("零不能做除数!");
            resultText.setText("零不能做除数!");
            opearteValidFlag=false;
        }else{
            resultNum/=getNumFromText();
        }
    }
    else if(operate.equals("X")){
        resultNum*=getNumFromText();
    }
    else if(operate.equals("+")){
        resultNum+=getNumFromText();
    }
    else if(operate.equals("-")){
        resultNum-=getNumFromText();
    }
    else if(operate.equals("=")){
        resultNum=getNumFromText();
    }
    if(opearteValidFlag){
        long t1=(long)resultNum;
        double t2=resultNum-t1;
        if(t2==0){
            resultText.setText(String.valueOf(t1));
        }else{
            resultText.setText(String.valueOf(new DecimalFormat("0.0000").format(resultNum)));
        }
    }
    operate=key;
    firstDigit=true;
    opearteValidFlag=true;

}
 private void doNumberKey(String key){
    //如果是第一个输入的数字或者符号后第一个数字
    if(firstDigit){
        if(key.equals(".")) /*resultText.setText(resultText.getText()+".");*/{
            //上来直接按.  
            if(resultNum==0&&operate=="=") resultText.setText(resultText.getText()+".");
            //上来先按了个别的运算符 在按.
            else{
                resultText.setText("0.");
               // resultText.setText("出错!");
                //opearteValidFlag=false;
            }
        }
        else resultText.setText(key);
    }else if(key.equals(".")&&resultText.getText().indexOf(".")<0){
        resultText.setText(resultText.getText()+".");
    }else if(!key.equals(".")){
        resultText.setText(resultText.getText()+key);
    }
    firstDigit=false;
}

private double getNumFromText(){
double result = 0;
try {
result = Double.valueOf(resultText.getText()).doubleValue();
} catch (NumberFormatException e) {
}
return result;

}
MyActionListener myActionListener=new MyActionListener();
public static void main(String[] args) {
    new MyCalculator().init();
}

}

二、讲解

1、创建我们所需的变量

计算器上的按键不少,我们都定义在一个keys数组当中,并且初始化一个buttons按钮数组。

除了我们的按钮之外,还有我们的输出显示窗口resultText,输出的结果我们都用resultNum来记录,之后在放到我们的输出窗口上。

其他的都写成注解了。

代码语言:javascript
复制
private JFrame frame=new JFrame("CSDN--哈__");
private String[] keys = {"%","C","CE","Back","1⁄x","X²","√x","÷","7","8","9",
"X","4","5","6","-","1","2","3","+","+/-","0",".","="};//计算器的功能键保存
private JButton [] buttons=new JButton[keys.length];//创建按钮
private JTextField resultText=new JTextField("0");//结果保存用于在计算器上显示
private double resultNum =0.0000;//用于保存运算的结果

private boolean firstDigit=true;//判断是否是第一个输入的数字,或者是运算符后第一个数字
private String operate ="=";//记录当前的运算符
private boolean opearteValidFlag =true;//判断当前输入是否合法</code></pre></div></div><h4 id="8kgmc" name="2.%E9%9D%A2%E6%9D%BF%E5%88%9D%E5%A7%8B%E5%8C%96">2.面板初始化</h4><p>面板初始化就是init方法,注释我都写了,这里不在讲了,也没啥重要的,就是美化一下面板。</p><h4 id="8er6m" name="3.%E6%B7%BB%E5%8A%A0%E6%8C%89%E9%92%AE%E4%BA%8B%E4%BB%B6%E7%9B%91%E5%90%AC%E6%9C%BA%E5%88%B6">3.添加按钮事件监听机制</h4><p>当我们点击计算机上的按钮的时候,计算器要给出反馈,这时就需要我们添加一个事件监听机制了。注释写好了,当我们点击不同的按钮的时候要处理不同的功能。</p><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0"> public class MyActionListener implements ActionListener{
    @Override
    public void actionPerformed(ActionEvent e) {
        String key = e.getActionCommand();
        //对于具有清除删除功能按键的处理(CE C BACK)
        if(key.equals(keys[1])||key.equals(keys[2])||key.equals(keys[3])){
            doDeleteKey(key);
        }
        //对只需要一个数值的按键处理(% 1/x x² √x  +/-  )
        else if(key.equals(keys[0])||key.equals(keys[4])||key.equals(keys[5])||key.equals(keys[6])||
                key.equals(keys[20])){
            doOperator1(key);

        }
        //对需要两个数值的按键的处理(÷ X - += )
        else if(key.equals(keys[7])||key.equals(keys[11])||key.equals(keys[15])||key.equals(keys[19])||
                key.equals(keys[23])){
            doOperator2(key);
        }
        //对数字按键进行处理(1 2 3 4 5 6 7 8 9 .)
        else{
            doNumberKey(key);
        }
    }
}</code></pre></div></div><h4 id="7qo1b" name="4.%E5%A4%84%E7%90%86%E5%AF%B9%E4%BA%8E%E5%85%B7%E6%9C%89%E6%B8%85%E9%99%A4%E5%88%A0%E9%99%A4%E5%8A%9F%E8%83%BD%E6%8C%89%E9%94%AE%E7%9A%84%E5%A4%84%E7%90%86(CE-C-BACK)">4.处理对于具有清除删除功能按键的处理(CE C BACK)</h4><p>计算器上有个清空按键C大家都用过吧,点了这个C之后我们所有的输入都会被初始化。倘若点了退格键那我们就把面板上的文字域删掉一个符号。比如我们输入的是111,点了退格之后就是11,当然你会想这只是文字域的变化,那我们保存的要计算的值为什么不变?别着急,真正开始计算是在我们点击了加减乘除这一类的符号的时候才会从面板读取值的。</p><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0"> private void doDeleteKey(String key){
    if(key.equals(&#34;CE&#34;)){
        resultText.setText(&#34;0&#34;);
    }
    else if(key.equals(&#34;C&#34;)){
        resultText.setText(&#34;0&#34;);
        resultNum=0.0000;
        firstDigit=true;
        opearteValidFlag=true;
        operate=&#34;=&#34;;
    }
    else{
        String text=resultText.getText();
        if(text.length()&gt;1){
            resultText.setText(text.substring(0,text.length()-1)); //如果内容长度大于1,那么直接删掉最后一个字符
        }else{
            //内容长度等于1
            resultText.setText(&#34;0&#34;);
            firstDigit=true;
        }
    }
}</code></pre></div></div><h4 id="c4nhi" name="5.%E4%B8%A4%E4%B8%AA%E6%95%B0%E8%BF%9B%E8%A1%8C%E8%BF%90%E7%AE%97%E5%8A%A0%E5%87%8F%E4%B9%98%E9%99%A4">5.两个数进行运算加减乘除</h4><p>上来先判断你当前的的符号是什么,并且也进行了一些错误情况的判断,如除数不能为0什么的。</p><p>下边你就能看到我们的resultNum被使用了。最后来个操作是否合法判断,如果合法并且输出结果最后是0那我们直接就把0输出到面板上,但是倘若我们的输出结果有精度差,那我们就得自己将0放到面板上了。</p><p><strong>注:我使用的浮点数计算并不是BigDecimal,所以存在精度差。</strong></p><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0">private void doOperator2(String key){
    if(operate.equals(&#34;÷&#34;)){
        if(getNumFromText()==0){
            //System.out.println(&#34;零不能做除数!&#34;);
            resultText.setText(&#34;零不能做除数!&#34;);
            opearteValidFlag=false;
        }else{
            resultNum/=getNumFromText();
        }
    }
    else if(operate.equals(&#34;X&#34;)){
        resultNum*=getNumFromText();
    }
    else if(operate.equals(&#34;+&#34;)){
        resultNum+=getNumFromText();
    }
    else if(operate.equals(&#34;-&#34;)){
        resultNum-=getNumFromText();
    }
    else if(operate.equals(&#34;=&#34;)){
        resultNum=getNumFromText();
    }
    if(opearteValidFlag){
        long t1=(long)resultNum;
        double t2=resultNum-t1;
        if(t2==0){
            resultText.setText(String.valueOf(t1));
        }else{
            resultText.setText(String.valueOf(new DecimalFormat(&#34;0.0000&#34;).format(resultNum)));
        }
    }
    operate=key;
    firstDigit=true;
    opearteValidFlag=true;

}</code></pre></div></div><p> 剩下的大家自己研究吧。</p>