[sunj的小白瞎搞系列 一]:如何用JAVA GUI 写一个简陋计算器

小白瞎搞系列 1:

Introduction :

今天上JAVA课遇到了一个很蠢的作业,为什么蠢呢,其实我对JAVA不算很熟,关键还是,老师让我们用GUI写界面.....

没错,你没听错。都什么时间了!? 都2024.5.13 晚上 22:18分了,还在写GUI。好吧,不狡辩了,就是不想写

那为什么笔者要发呢, 夜深了发牢骚

作业是做一个Calculator(demo),说到demo,笔者顺便预告一下,笔者正在谋划一个大项目--从零实现操作系统demo版本

其实也还好了,有参考书,而且不光笔者在做,MIT,Tsinghua都在做,今天OS课上,老师还让我们做了HIT的OS一小节

确实深深的被OS吸引住了,虽然我主要major in AI,但是很好玩,以至于我论文都没看,代码也没跑

关于星期四要组会但我一篇论文都没看,代码没有跑,纯在瞎搞并且极度后悔的我

Code :

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Experiment4_2_22 extends JFrame implements ActionListener {
    private JTextField outputField;
    private StringBuilder stringBuffer = new StringBuilder();
    JPanel jPanel = new JPanel();

    Experiment4_2_22() {
        setTitle("Calculate");
        setSize(500, 500);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        setLayout(new BorderLayout());

        outputField = new JTextField();
        outputField.setHorizontalAlignment(JTextField.CENTER);
        outputField.setEditable(false);
        add(outputField, BorderLayout.NORTH);

        jPanel.setLayout(new GridLayout(4, 4));
        String[] buttons = {
                "7", "8", "9", "/",
                "4", "5", "6", "*",
                "1", "2", "3", "+",
                "0", ".", "=", "-"
        };
        for (String button : buttons) {
            JButton jButton = new JButton(button);
            jButton.addActionListener(this);
            jPanel.add(jButton);
        }
        add(jPanel);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        String command = e.getActionCommand();
        if (command.equals("=")) {
            try {
                //用eval作为处理函数,减少冗杂
                double result = eval(stringBuffer.toString());
                outputField.setText(String.valueOf(result));
                stringBuffer.setLength(0);
                stringBuffer.append(result);
            } catch (ArithmeticException ex) {
                outputField.setText("Error");
                stringBuffer.setLength(0);
            }
        } else {
            stringBuffer.append(command);
            outputField.setText(stringBuffer.toString());
        }
    }

    private double eval(String expression) {
        // 如果表达式为空或长度为0,则返回0
        if (expression == null || expression.length() == 0) {
            return 0;
        }

        double res = 0;
        String[] tmp;

        // 根据运算符分割表达式并执行相应的计算
        if (expression.contains("+")) {
            tmp = expression.split("\\+");
            double n1 = Double.parseDouble(tmp[0]);
            double n2 = Double.parseDouble(tmp[1]);
            res = n1 + n2;
        } else if (expression.contains("-")) {
            tmp = expression.split("-");
            double n1 = Double.parseDouble(tmp[0]);
            double n2 = Double.parseDouble(tmp[1]);
            res = n1 - n2;
        } else if (expression.contains("*")) {
            tmp = expression.split("\\*");
            double n1 = Double.parseDouble(tmp[0]);
            double n2 = Double.parseDouble(tmp[1]);
            res = n1 * n2;
        } else if (expression.contains("/")) {
            tmp = expression.split("/");
            double n1 = Double.parseDouble(tmp[0]);
            double n2 = Double.parseDouble(tmp[1]);
            // 检查除数是否为0
            if (n2 != 0) {
                res = n1 / n2;
            } else {
                // 如果除数为0,返回0或者抛出异常,这里返回0
                res = 0;
            }
        } else {
            // 如果表达式中没有运算符,则直接将表达式解析为双精度浮点数
            res = Double.parseDouble(expression);
        }

        return res;
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            Experiment4_2_22 e = new Experiment4_2_22();
            e.setVisible(true);
        });
    }
}

出于保险,读者还是解释一下把,防止你的语言基础不熟

JTextField outputField;

首先这个就是一个文本框, 叫JTextField

可以看到在source 里面他是一个swing的框架,说了跟没说一样

这里有几个比较重要的函数:第一个是setHorizontalAlignment,可以很明显的知道里面有很多方位词,所以肯定是用来判断方位的

第二个是setEditable,看不懂没关系,反正设为false就是不可修改的

接下来,是add这个函数

这个函数很清晰,意思就是在哪个component add‘,约束条件是哪个constraint

好啦,我铺垫了这么多基础知识,你应该能看懂一点我之前的代码啦。 加油!

接下来这个 JPanel的东西是用来布局的,注意他跟JFrame的布局是有区别的。JFrame是整体的,JPanel是用来把容器连在一起的,就例如,JButton要add在JPanel上。

JPanel jPanel = new JPanel();

(#`O′),别困了,给你个小任务

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);

查查这两行代码作用于谁?代码是什么意思?

再查查

new GridLayout()
new BorderLayout()

是什么意思?

好啦,你查完了吧,我们继续吧。

我们看到这一段。

我们说说处理事件的逻辑,我们首先用getActionCommand()去得到动作对象的字符串,什么东西?

LLM讲的很好。我这里顺便也问了getSource()与之的区别,getSource()是什么?谷歌吧。 _

String command = e.getActionCommand();
if (command.equals("=")) {
    try {
        //用eval作为处理函数,减少冗杂
        double result = eval(stringBuffer.toString());
        outputField.setText(String.valueOf(result));
        stringBuffer.setLength(0);
        stringBuffer.append(result);
    } catch (ArithmeticException ex) {
        outputField.setText("Error");
        stringBuffer.setLength(0);
    }
} else {
    stringBuffer.append(command);
    outputField.setText(stringBuffer.toString());
}

这里我们是要做一个计算器,那肯定要用stringBuffer去做,因为他是个动态字符串,JAVA不像Cpp,他的string是个常值,所以我们这里得用stringBuffer

然后在去转string去输出到outputField。假如没遇到"="之前,那就一直加,显示一直打出来,遇到了就进行处理,每次处理完,就设置stringBuffer长度为0,即是设置为空值的意思,然后具体怎么实现呢,请看eval函数,很简单的,我就不讲解了。

private double eval(String expression) {
    // 如果表达式为空或长度为0,则返回0
    if (expression == null || expression.length() == 0) {
        return 0;
    }

    double res = 0;
    String[] tmp;

    // 根据运算符分割表达式并执行相应的计算
    if (expression.contains("+")) {
        tmp = expression.split("\\+");
        double n1 = Double.parseDouble(tmp[0]);
        double n2 = Double.parseDouble(tmp[1]);
        res = n1 + n2;
    } else if (expression.contains("-")) {
        tmp = expression.split("-");
        double n1 = Double.parseDouble(tmp[0]);
        double n2 = Double.parseDouble(tmp[1]);
        res = n1 - n2;
    } else if (expression.contains("*")) {
        tmp = expression.split("\\*");
        double n1 = Double.parseDouble(tmp[0]);
        double n2 = Double.parseDouble(tmp[1]);
        res = n1 * n2;
    } else if (expression.contains("/")) {
        tmp = expression.split("/");
        double n1 = Double.parseDouble(tmp[0]);
        double n2 = Double.parseDouble(tmp[1]);
        // 检查除数是否为0
        if (n2 != 0) {
            res = n1 / n2;
        } else {
            // 如果除数为0,返回0或者抛出异常,这里返回0
            res = 0;
        }
    } else {
        // 如果表达式中没有运算符,则直接将表达式解析为双精度浮点数
        res = Double.parseDouble(expression);
    }

    return res;
}

对了,最后说一点,

SwingUtilities.invokeLater(() -> {
    Experiment4_2_22 e = new Experiment4_2_22();
    e.setVisible(true);
});

因为我们进行GUI编程的时候,很多时候会多线程操作,会有一点安全问题,具体请谷歌,蛮复杂的。

所以我们得用SwingUtilities.invokeLater()去保证安全。

invokeLater(接受一个对象),一旦执行,这个任务会被放入事件队列中,等待事件分发线程去执行。这样就确保了在正确的线程上执行 GUI 相关的操作,避免了多线程导致的并发访问问题。

至此全篇结束

posted @ 2024-05-13 23:18  Cansal7  阅读(47)  评论(0)    收藏  举报