Java学习之路-GUI-网格布局实现计算器

实现简易计算器, 具有简单的计算功能
package GUI;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.swing.*;
import javax.swing.text.BadLocationException;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class CalculatorDemo {

    public JFrame jf;
    public JPanel jp, jp1;
    public JTextArea jTextArea;
    public JButton[] jButtons = {
            new JButton("MC"), new JButton("MR"), new JButton("MS"),
            new JButton("M+"), new JButton("M-"), new JButton("←"),
            new JButton("CE"), new JButton("C"), new JButton("±"),
            new JButton("√"), new JButton("7"), new JButton("8"),
            new JButton("9"), new JButton("/"), new JButton("%"),
            new JButton("4"), new JButton("5"), new JButton("6"),
            new JButton("*"), new JButton("1/x"), new JButton("1"),
            new JButton("2"), new JButton("3"), new JButton("-"),
            new JButton("="), new JButton("0"), new JButton("."),
            new JButton("+"), new JButton("("), new JButton(")")
    };
    //↑直接将按钮对象按顺序丢到数组里面, 按钮叫啥都不用管

    public CalculatorDemo(){

        int i;
        jf = new JFrame("计算器");
        jf.setSize(350, 310);
        jf.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        jf.setLocationRelativeTo(null);
        jf.setResizable(false);

        jp = new JPanel(new FlowLayout());
        jp1 = new JPanel(new GridLayout(6,5,10,10));
        //↑创建1个流式布局jp , 用于存放文本区域jTextArea和网格布局jp1, jp1中存放计算器的各个按钮

        jTextArea = new JTextArea(2,22);
        jTextArea.setFont(new Font(null, Font.PLAIN, 18));
        jTextArea.setLineWrap(false);
        jTextArea.setEnabled(false);
        jTextArea.setText("\n0");
        //↑创建拥有2列的文本区域, 设置自动换行与可编辑为false, 并设置编辑框内容\n0

        for(i = 0; i < 30; i++) {
            jButtons[i].addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent actionEvent) {
                    try {
                        inputChar(actionEvent.getActionCommand());
                    } catch (BadLocationException | ScriptException e) {
                        e.printStackTrace();
                    }
                }
            });
            //↑通过for循环对每个按钮注册监听事件, 并在按下后调用inputChar()方法

            jp1.add(jButtons[i]);
            //↑通过for循环将按钮按顺序加入网格布局jp1中
        }
        jp.add(jTextArea);
        jp.add(jp1);
        //↑将文本区域jTextArea与网格布局jp1加入流式布局jp中

        jf.setContentPane(jp);
        jf.setVisible(true);
    }

    public void inputChar (String s) throws BadLocationException, ScriptException {
        int start1, end1, start2, end2;
        start1 = jTextArea.getLineStartOffset(0);
        //↑获取文本区域中第一行的行首(包括换行符)在全文中的偏移量
        end1 = jTextArea.getLineEndOffset(0);
        //↑获取文本区域中第一行的行尾(包括换行符)在全文中的偏移量
        start2 = jTextArea.getLineStartOffset(1);
        //↑获取文本区域中第二行的行首(包括换行符)在全文中的偏移量
        end2 = jTextArea.getLineEndOffset(1);
        //↑获取文本区域中第二行的行尾(包括换行符)在全文中的偏移量

        //System.out.println(start1 + "," + end1 + "," + start2 + "," + end2);

        //↓通过按钮内容判断按下了哪个按钮
        if(s.equals("←")){
            //↓如果第一行除了换行符还存在其他内容则执行
            if(end1 - start1 > 1) {
                //↓通过偏移量获取第一行内容(包括第一行行末的换行符\n)
                String cache = jTextArea.getText(start1, end1 - start1);
                //↓截取取第一行除最后两个字符(最后一个字符是换行符)的字符串并加上第二行字符串
                jTextArea.setText(cache.substring(0, cache.length() - 2)
                        + "\n" + jTextArea.getText(start2, end2 - start2));
            }
        }else if(s.equals("CE")){
            //↓清除第二行结果
            jTextArea.setText(jTextArea.getText(start1,end1 - start1 - 1) + "\n0");
        }else if(s.equals("C")){
            //↓清除所有内容(归零)
            jTextArea.setText("\n0");
        }else if(s.equals("=")){
            //↓获取第一行表达式并调用JS计算结果
            ScriptEngine jsEn = new ScriptEngineManager().getEngineByName("JavaScript");
            jTextArea.setText(jsEn.eval(jTextArea.getText(start1,end1 - start1)) +
                    "\n" + jsEn.eval(jTextArea.getText(start1,end1 - start1)));
        }else if(s.equals("+") || s.equals("-") || s.equals("*") || s.equals("/") || s.equals("%")){
            String s1 = jTextArea.getText(start1, end1 - start1 - 1);
            //↓如果第一行表达式左右括号数量相等则将运算结果显示到第二行并将内容添加到第一行末,
            // 否则不进行运算直接将内容添加到第一行末
            if(strCount(s1, "(") == strCount(s1, ")")) {
                ScriptEngine jsEn = new ScriptEngineManager().getEngineByName("JavaScript");
                jTextArea.setText(jTextArea.getText(start1, end1 - start1 - 1) + s +
                        "\n" + jsEn.eval(jTextArea.getText(start1, end1 - start1)));
            }else{
                jTextArea.setText(jTextArea.getText(start1, end1 - start1 - 1) + s +
                        "\n" + jTextArea.getText(start2,end2 - start2));
            }
        }else if(s.equals("0") || s.equals("1") || s.equals("2") || s.equals("3") || s.equals("4")
                || s.equals("5") || s.equals("6") || s.equals("7") || s.equals("8") || s.equals("9")
                || s.equals(".") || s.equals("(") || s.equals(")")){
            //将内容添加到第一行末
            jTextArea.setText(jTextArea.getText(start1,end1 - start1 - 1) + s +
                    "\n" + jTextArea.getText(start2,end2 - start2));
        }

        //System.out.println("当前表达式:『" + jTextArea.getText(jTextArea.getLineStartOffset(0),
        //jTextArea.getLineEndOffset(0) - jTextArea.getLineStartOffset(0) - 1) + "』");
        //System.out.println("点击了:『" + s + "』按钮");
    }

    //↓返回str2在str1中出现的次数
    public int strCount(String str1, String str2){
        return (str1.length()-str1.replace(str2, "").length())/str2.length();
    }

    public static void main (String[] args){
        new CalculatorDemo();
    }
}
字符串转计算表达式, 调用了JS的方法,
不过IDE提示: Nashorn engine is planned to be removed from a future JDK release
ScriptEngine在以后将被弃用的样子, 虽然不是很懂,
反正也就是随便用用, 就不过多的讨论这玩意了
点赞

发表评论

电子邮件地址不会被公开。必填项已用 * 标注