Java GUI图形编程 使用awt和swing 制作简易计算器的工具包含源码和讲解 / java练习项目

系列文章目录

提示:阅读本章之前,请先阅读目录



前言

通过学习java 的gui编程,可以快速学习java基础语法,让我们来看看如何制作一个简易计算器,以下包含全部源码。

简易计算器 v1.2 图形界面

在这里插入图片描述
计算过程的界面

在这里插入图片描述


一、常规配置

1. 设置窗口大小

setSize(600, 590);

2. 获取当前屏幕的尺寸

int screenWidth = (int)Toolkit.getDefaultToolkit().getScreenSize().getWidth();
int screenHeight = (int)Toolkit.getDefaultToolkit().getScreenSize().getHeight();
// 最后可用于设置窗口位置
setLocation(screenWidth/3, screenHeight/6);

3. 窗口居中

setLocationRelativeTo(null);

4. 设置窗口名称

setTitle(title);

5. 添加监听器,关闭窗口

frame.addWindowListener(new WindowAdapter() {
    @Override
    public void windowClosing(WindowEvent e) {
        System.exit(0);
    }
});

6. 设置窗口可见性

 frame.setVisible(true);

7. 设置文本框不可编辑

jTextField1.setEditable(false);

8. 设置文本框提示

jTextField1.setToolTipText("请输入计算数字");

9. 设置文本框的尺寸大小

jTextField1.setPreferredSize(new Dimension(580, 40));

10. 设置文本框的字体样式

jTextField1.setFont(new Font("", Font.BOLD, 20));

11. 设置文本域的滚动条

JTextArea jTextArea1 = new JTextArea();
JScrollPane sp = new JScrollPane(jTextArea1);
sp.setPreferredSize(new Dimension(580, 160));
p7.add(sp);

12. 弹出框提示

JOptionPane.showMessageDialog(null,"暂时不支持超过10位数字的计算");

13. 警告弹出框提示

JOptionPane.showMessageDialog(null, "系统出现了计算错误", "系统报错 " + "可联系管理员处理", JOptionPane.ERROR_MESSAGE);

二、目录结构

ButtonListener.java   按键监听器,主要进行处理各种按键之后的事件,算法
Calculator.java   入口程序
MyFrame.java   创建一个frame窗口
SetComponent.java   绘制界面,按钮,面板,输入框
WindowClose.java  监听窗口关闭
WindowVisible.java  设置窗口为可见性

三、Calculator.java,入口

package com.tools;

public class Calculator {
    public static void main(String[] args) {
        // 初始化窗口
        MyFrame myFrame = new MyFrame("Smobee Calculator v1.2");
        // 初始化组件
        new SetComponent(myFrame);
        // 设置监听关闭
        new WindowClose(myFrame);
        // 设置窗口加载完,就显示可见
        new WindowVisible(myFrame);
    }
}

四、MyFrame.java 创建窗口frame

package com.tools;

import java.awt.*;

public class MyFrame extends Frame {
    MyFrame(String title) {
        // 设置窗口大小
        setSize(600, 590);
        // 窗口居中
        setLocationRelativeTo(null);
        // 设置窗口名称
        setTitle(title);
    }
}

五、WindowClose.java,监听关闭

package com.tools;

import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

public class WindowClose {
    WindowClose(Frame frame) {
        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                // 监听到点击关闭按钮,关闭程序
                System.exit(0);
            }
        });
    }
}

六、WindowVisible.java,设置窗口可见性

要在所有的组件添加完毕之后,再设置窗口可见性,要不然,第一次显示窗口,会是一片空白

package com.tools;

import java.awt.*;

public class WindowVisible {
    WindowVisible(Frame frame) {
        // 设置frame窗口,为可见
        frame.setVisible(true);
    }
}

七、SetComponent.java,绘制各种组件

package com.tools;

import javax.swing.*;
import javax.swing.text.Highlighter;
import java.awt.*;

public class SetComponent {
    JButton jButton1,jButton2,jButton3,jButton4,jButton5,jButton6,jButton7,jButton8,jButton9,jButton10,jButton11,jButton12,jButton13,jButton14,jButton15,jButton16,jButton17,jButton18,jButton19,jButton20;
    JTextField jTextField1;
    JTextArea jTextArea1;
    // 两个数
    double number1, number2;
    // 当前第几个数
    int selectNumber = 1;
    // 是否为小数点
    boolean isFloat = false;
    // 当前算法 0 无 1 加 2 减 3 乘 4 除 5 除...余
    String algo = "no";
    // 第一个数字激活状态
    boolean number1State = false;
    // 第二个数字激活状态
    boolean number2State = false;
    // 是否计算结束
    boolean calcState = false;
    SetComponent(Frame frame) {
        // 创建整体的面板
        Panel panel = new Panel();
        // 第一层
        Panel p1 = new Panel(new FlowLayout());
        jTextField1 = new JTextField();
        jTextField1.setEditable(false);
        jTextField1.setToolTipText("请输入计算数字");
        jTextField1.setPreferredSize(new Dimension(580, 40));
        jTextField1.setFont(new Font("", Font.BOLD, 20));
        p1.add(jTextField1);
        // 第二层
        Panel p2 = new Panel(new GridLayout(1, 4));
        jButton1 = new JButton("C");
        jButton2 = new JButton("÷");
        jButton3 = new JButton("*");
        jButton4 = new JButton("Del");
        jButton1.setPreferredSize(new Dimension(145, 60));
        jButton1.addActionListener(new ButtonListener(this));
        jButton2.addActionListener(new ButtonListener(this));
        jButton3.addActionListener(new ButtonListener(this));
        jButton4.addActionListener(new ButtonListener(this));
        // 第三层
        Panel p3 = new Panel(new GridLayout(1, 4));
        jButton5 = new JButton("7");
        jButton6 = new JButton("8");
        jButton7 = new JButton("9");
        jButton8 = new JButton("-");
        jButton5.setPreferredSize(new Dimension(145, 60));
        jButton5.addActionListener(new ButtonListener(this));
        jButton6.addActionListener(new ButtonListener(this));
        jButton7.addActionListener(new ButtonListener(this));
        jButton8.addActionListener(new ButtonListener(this));
        // 第四层
        Panel p4 = new Panel(new GridLayout(1, 4));
        jButton9 = new JButton("4");
        jButton10 = new JButton("5");
        jButton11 = new JButton("6");
        jButton12 = new JButton("+");
        jButton9.setPreferredSize(new Dimension(145, 60));
        jButton9.addActionListener(new ButtonListener(this));
        jButton10.addActionListener(new ButtonListener(this));
        jButton11.addActionListener(new ButtonListener(this));
        jButton12.addActionListener(new ButtonListener(this));
        // 第五层
        Panel p5 = new Panel(new GridLayout(1, 4));
        jButton13 = new JButton("1");
        jButton14 = new JButton("2");
        jButton15 = new JButton("3");
        jButton16 = new JButton("√");
        jButton13.setPreferredSize(new Dimension(145, 60));
        jButton13.addActionListener(new ButtonListener(this));
        jButton14.addActionListener(new ButtonListener(this));
        jButton15.addActionListener(new ButtonListener(this));
        jButton16.addActionListener(new ButtonListener(this));
        // 第六层
        Panel p6 = new Panel(new GridLayout(1, 4));
        jButton17 = new JButton("%");
        jButton18 = new JButton("0");
        jButton19 = new JButton(".");
        jButton20 = new JButton("=");
        jButton17.setPreferredSize(new Dimension(145, 60));
        jButton17.addActionListener(new ButtonListener(this));
        jButton18.addActionListener(new ButtonListener(this));
        jButton19.addActionListener(new ButtonListener(this));
        jButton20.addActionListener(new ButtonListener(this));
        // 第七层
        Panel p7 = new Panel(new GridLayout(1, 1));
        jTextArea1 = new JTextArea();
        JScrollPane sp = new JScrollPane(jTextArea1);
        sp.setPreferredSize(new Dimension(580, 160));
        jTextArea1.setText("历史计算:");
        jTextArea1.setEditable(false);
        // 放进容器
        panel.add(p1);
        p2.add(jButton1);
        p2.add(jButton2);
        p2.add(jButton3);
        p2.add(jButton4);
        p3.add(jButton5);
        p3.add(jButton6);
        p3.add(jButton7);
        p3.add(jButton8);
        p4.add(jButton9);
        p4.add(jButton10);
        p4.add(jButton11);
        p4.add(jButton12);
        p5.add(jButton13);
        p5.add(jButton14);
        p5.add(jButton15);
        p5.add(jButton16);
        p6.add(jButton17);
        p6.add(jButton18);
        p6.add(jButton19);
        p6.add(jButton20);
        p7.add(sp);
        panel.add(p2);
        panel.add(p3);
        panel.add(p4);
        panel.add(p5);
        panel.add(p6);
        panel.add(p7);
        frame.add(panel);
    }
}

八、ButtonListener.java 按键监听器,处理按键事件

这里主要进行各种算法的运算,其中,就用到比较简单的方法,没有用Math进行算法,主要是为了练习,如果您追求细节,可以尝试修改代码,使其更加符合标准计算器的算法


本程序,还尚有许多bug,主要是时间不够,各位同学如发现有计算bug,可以提交到评论区或私信,同学们也可以发挥个人能力

package com.tools;

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

public class ButtonListener implements ActionListener {
    SetComponent setComponent;

    ButtonListener(SetComponent setComponent) {
        this.setComponent = setComponent;
    }

    private void setText(Double result) {
        if (this.setComponent.isFloat || this.setComponent.algo.equals("÷")) {
            DecimalFormat df = new DecimalFormat("0.00");
            this.setComponent.jTextField1.setText(Double.toString(Double.parseDouble(df.format(result))));
        } else {
            int x = (int) Math.round(result);
            this.setComponent.jTextField1.setText(Integer.toString(x));
        }
    }

    private void clearNunber(Boolean clearText, Boolean clearCalc) {
        if (clearText) {
            this.setComponent.jTextField1.setText("");
        }
        if (clearCalc) {
            this.setComponent.calcState = false;
        }
        this.setComponent.selectNumber = 1;
        this.setComponent.number1 = 0;
        this.setComponent.number2 = 0;
        this.setComponent.number1State = false;
        this.setComponent.number2State = false;
        this.setComponent.isFloat = false;
        this.setComponent.algo = "no";
    }

    private void calcNumber() {
        double result = 0;
        // 判断两个数,是否都输入了
        if (this.setComponent.number1State && this.setComponent.number2State) {
            String algo = this.setComponent.algo;
            if (algo.equals("*")) {
                result = this.setComponent.number1 * this.setComponent.number2;
            } else if (algo.equals("÷")) {
                result = this.setComponent.number1 / this.setComponent.number2;
            } else if (algo.equals("-")) {
                result = this.setComponent.number1 - this.setComponent.number2;
            } else if (algo.equals("+")) {
                result = this.setComponent.number1 + this.setComponent.number2;
            } else if (algo.equals("%")) {
                result = this.setComponent.number1 % this.setComponent.number2;
            } else if (algo.equals("√")) {
                result = Math.sqrt(this.setComponent.number1);
            }
            this.setText(result);
            this.addHistory();
            // 恢复初始化
            this.clearNunber(false, false);
        } else if (this.setComponent.number1State && this.setComponent.algo.equals("√")) {
            String algo = this.setComponent.algo;
            result = Math.sqrt(this.setComponent.number1);
            this.setText(result);
            this.addHistory();
            // 恢复初始化
            this.clearNunber(false, false);
        }
    }

    private void addHistory() {
        this.setComponent.calcState = true;
        if (this.setComponent.isFloat) {
            double a = this.setComponent.number1;
            String b = "";
            if (!this.setComponent.algo.equals("√")) {
                b = Double.toString(this.setComponent.number2);
            }
            String text = "\n" + a + this.setComponent.algo + b + "=" + this.setComponent.jTextField1.getText();
            this.setComponent.jTextArea1.setText(this.setComponent.jTextArea1.getText() + text);
        } else {
            int a = (int) Math.round(this.setComponent.number1);
            String b = "";
            if (!this.setComponent.algo.equals("√")) {
                b = Integer.toString((int)Math.round(this.setComponent.number2));
            }
            String text = "\n" + a + this.setComponent.algo + b + "=" + this.setComponent.jTextField1.getText();
            this.setComponent.jTextArea1.setText(this.setComponent.jTextArea1.getText() + text);
        }
    }

    private void addHistory(String text) {
        this.setComponent.jTextArea1.setText(this.setComponent.jTextArea1.getText() + text);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        String name = e.getActionCommand();
        String numberS = "1234567890";
        String funcS = "÷*-+√%";
        String text = this.setComponent.jTextField1.getText();
        // 清除内容
        if (name.equals("C")) {
            this.clearNunber(true, true);
        }
        // 加减乘除
        if (funcS.contains(name)) {
            if (this.setComponent.jTextField1.getText().length() == 0 && name.equals("-")) {
                this.setComponent.jTextField1.setText("-");
            } else {
                this.setComponent.jTextField1.setText("");
            }
            if (this.setComponent.calcState) {
                this.setComponent.number1State = true;
                this.setComponent.number1 = Double.parseDouble(text);
            }
            if (this.setComponent.number1State) {
                this.setComponent.algo = name;
                this.setComponent.selectNumber = 2;
            }
        }
        // 小数点
        if (name.equals(".")) {
            // 判断是否已经存在小数点
            if (!text.contains(".") && text.length() > 0) {
                this.setComponent.jTextField1.setText(text + ".");
            }
            this.setComponent.isFloat = true;
        }
        // 删除最后一个字符
        if (name.equals("Del")) {
            if (text.length() > 0) {
                String newText = text.substring(0, text.length()-1);
                this.setComponent.jTextField1.setText(newText);
            }
        }
        // 判断等于号
        if (name.equals("=")) {
           // 计算
            try {
                this.calcNumber();
            } catch (Throwable ex) {
                String textError = "\n【系统错误】程序运行发生错误\n【错误信息】" + ex + "\n【计算参数】" + this.setComponent.number1 + this.setComponent.algo + this.setComponent.number2 + "\n【联系方式】请将该情况反馈给管理员处理!Smobee";
                System.out.println(textError);
                addHistory(textError);
                JOptionPane.showMessageDialog(null, textError, "系统报错 " + "可联系管理员处理 Smobee", JOptionPane.ERROR_MESSAGE);
            }
        }
        // 判断按键0~9
        if (numberS.contains(name)) {
            // 判断是不是超过10位
            if (text.length() >= 10) {
                JOptionPane.showMessageDialog(null,"暂时不支持超过10位数字的计算");
                return;
            }
            // 判断如果当前已经为0,输入0,则不继续增加
            if(text.equals("0")) {
                return;
            }
            // 判断是不是结束了计算状态
            if (this.setComponent.calcState) {
                this.setComponent.jTextField1.setText("");
                this.setComponent.calcState = false;
            }
            // 获取当前文本框的值
            String text3 = this.setComponent.jTextField1.getText();
            this.setComponent.jTextField1.setText(text3 + name);
            String text1 = this.setComponent.jTextField1.getText();
            // 判断是第一个数字,还是第二个数字
            if (this.setComponent.selectNumber == 1) {
                this.setComponent.number1State = true;
                this.setComponent.number1 = Double.parseDouble(text1);
            } else if (this.setComponent.selectNumber == 2) {
                this.setComponent.number2State = true;
                this.setComponent.number2 = Double.parseDouble(text1);
            }
        }
    }
}

九、异常处理

我在计算的关键地方,加了异常处理,这样的话,程序就不会闪退,并且提示用户

// 判断等于号
if (name.equals("=")) {
   // 计算
    try {
        this.calcNumber();
    } catch (Throwable ex) {
        String textError = "\n【系统错误】程序运行发生错误\n【错误信息】" + ex + "\n【计算参数】" + this.setComponent.number1 + this.setComponent.algo + this.setComponent.number2 + "\n【联系方式】请将该情况反馈给管理员处理!Smobee";
        System.out.println(textError);
        addHistory(textError);
        JOptionPane.showMessageDialog(null, textError, "系统报错 " + "可联系管理员处理 Smobee", JOptionPane.ERROR_MESSAGE);
    }
}

在这里插入图片描述

十、exe4j Wizard 使用生成exe

1. 先在 IntelliJ IDEA 安装Handy Export Jar在这里插入图片描述

2. 然后导出为jar包

在这里插入图片描述

通过jar包,我们就可以直接生成exe文件

在这里插入图片描述

3. 打开exe4j Wizard

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

最后一步,生成exe

在这里插入图片描述

在这里插入图片描述

可以直接打开

在这里插入图片描述


更新日志

提示:将会持续优化更新

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值