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

news2025/2/28 21:38:50

  📝个人主页:哈__

期待您的关注 

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

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

直接上源码,后上讲解。

一、源码

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来记录,之后在放到我们的输出窗口上。

其他的都写成注解了。

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;//判断当前输入是否合法

2.面板初始化

面板初始化就是init方法,注释我都写了,这里不在讲了,也没啥重要的,就是美化一下面板。

3.添加按钮事件监听机制

当我们点击计算机上的按钮的时候,计算器要给出反馈,这时就需要我们添加一个事件监听机制了。注释写好了,当我们点击不同的按钮的时候要处理不同的功能。

 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);
            }
        }
    }

4.处理对于具有清除删除功能按键的处理(CE C BACK)

计算器上有个清空按键C大家都用过吧,点了这个C之后我们所有的输入都会被初始化。倘若点了退格键那我们就把面板上的文字域删掉一个符号。比如我们输入的是111,点了退格之后就是11,当然你会想这只是文字域的变化,那我们保存的要计算的值为什么不变?别着急,真正开始计算是在我们点击了加减乘除这一类的符号的时候才会从面板读取值的。

 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;
            }
        }
    }

5.两个数进行运算加减乘除

上来先判断你当前的的符号是什么,并且也进行了一些错误情况的判断,如除数不能为0什么的。

下边你就能看到我们的resultNum被使用了。最后来个操作是否合法判断,如果合法并且输出结果最后是0那我们直接就把0输出到面板上,但是倘若我们的输出结果有精度差,那我们就得自己将0放到面板上了。

注:我使用的浮点数计算并不是BigDecimal,所以存在精度差。

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;

    }

 剩下的大家自己研究吧。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1585021.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

48-基于腾讯云EKS的容器化部署实战

准备工作 在部署IAM应用之前&#xff0c;我们需要做以下准备工作&#xff1a; 开通腾讯云容器服务镜像仓库。安装并配置Docker。准备一个Kubernetes集群。 开通腾讯云容器服务镜像仓库 在Kubernetes集群中部署IAM应用&#xff0c;需要从镜像仓库下载指定的IAM镜像&#xff…

基于springboot实现医院管理系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现医院管理系统演示 摘要 随着信息互联网信息的飞速发展&#xff0c;医院也在创建着属于自己的管理系统。本文介绍了医院管理系统的开发全过程。通过分析企业对于医院管理系统的需求&#xff0c;创建了一个计算机管理医院管理系统的方案。文章介绍了医院管理系…

【YOLOv8实战】手把手带你入门YOLOv8,你也能训练自己的检测器,以SAR目标检测为例(源码+数据集+Gradio界面)

&#x1f4a1;&#x1f4a1;&#x1f4a1;本文摘要&#xff1a;基于YOLOv8的SAR图像目标检测系统&#xff0c;覆盖数据制作、数据可视化、模型训练/评估/推理/部署全流程&#xff0c;最后通过 Gradio 界面进行展示。 0 写在前面 上篇分享【飞浆AI实战】交通灯检测&#xff1a…

抖音视频无水印采集拓客软件|视频批量下载提取工具

抖音视频无水印批量采集拓客软件助力高效营销&#xff01; 随着抖音平台的崛起&#xff0c;视频已成为各行各业进行营销的重要工具。但是&#xff0c;传统的视频下载方式往往效率低下&#xff0c;无法满足快速获取大量视频的需求。针对这一问题&#xff0c;我们开发了一款视频无…

Java项目:基于SSM+vue框架实现的人力资源管理系统设计与实现(源码+数据库+毕业论文+任务书)

一、项目简介 本项目是一套基于SSM框架实现的人力资源管理系统 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#xff0c;eclipse或者idea 确保可以运行&#xff01; 该系统功能完善、界面美观、操作简单、功能…

中介者模式【行为模式C++】

1.简介 中介者模式是一种行为设计模式&#xff0c; 能让你减少对象之间混乱无序的依赖关系。 该模式会限制对象之间的直接交互&#xff0c; 迫使它们通过一个中介者对象进行合作。 亦称&#xff1a; 调解人、控制器、Intermediary、Controller、Mediator 2.示例 中介者模式在…

【氧化镓】β-Ga2O3肖特基势垒二极管的缺陷识别

本文是一篇关于β-Ga2O3肖特基势垒二极管在电子辐射和退火调节下缺陷识别的研究。文章首先介绍了β-Ga2O3作为一种高性能器件材料的重要性&#xff0c;然后详细描述了实验方法&#xff0c;包括样品制备、电子辐照、热退火处理以及电学特性和深能级瞬态谱&#xff08;DLTS&#…

深度学习环境搭建问题汇总

pip无法通过国内源下载&#xff0c;could not find a version that satisfies the requirement 当遇见could not find a version that satisfies the requirement问题时&#xff0c;可以通过下载whl的方式进行离线安装&#xff0c;以torch1.12.0为例&#xff0c;如果用的是阿里…

一网统管/安防监控/视频综合管理EasyCVR视频汇聚平台解决方案

一、当前现状分析 当前视频资源面临以下问题&#xff1a; 1&#xff09;不同单位在视频平台建设中以所属领域为单位&#xff0c;设备品牌众多&#xff0c;存在的标准不一&#xff0c;各系统之间也没有统一标准&#xff1b; 2&#xff09;各单位视频平台建设分散、统筹性差&a…

机器学习和深度学习 -- 李宏毅(笔记与个人理解1-6)

机器学习和深度学习教程 – 李宏毅&#xff08;笔记与个人理解&#xff09; day1 课程内容 什么是机器学习 找函数关键技术&#xff08;深度学习&#xff09; 函数 – 类神经网络来表示 &#xff1b;输入输出可以是 向量或者矩阵等如何找到函数&#xff1a; supervised Lear…

Redis 最佳实践 [后端必看]

文章目录 1. Redis 键值设计1.1 优雅的 key 结构1.2 拒绝 BigKeyBigKey的危害如何发现BigKey①redis-cli --bigkeys② scan 扫描③第三方监控④网络监控 如何删除 BigKey 1.3 恰当的数据类型总结&#xff1a; 2. 批处理优化3. 服务器端优化-持久化配置4. 服务器端优化-慢查询优…

产品经理有门槛吗?

转行NPDP也是很合适的一条发展路径&#xff0c;之后从事新产品开发相关工作~ 一、什么是NPDP&#xff1f; NPDP 是产品经理国际资格认证&#xff0c;美国产品开发与管理协会&#xff08;PDMA&#xff09;发起的&#xff0c;是目前国际公认的唯一的新产品开发专业认证&#xff…

移植 amd blas 到 cuda 生态

1&#xff0c;下载源码 GitHub - ROCm/rocBLAS: Next generation BLAS implementation for ROCm platform $ git clone --recursive https://github.com/ROCm/rocBLAS.git 2&#xff0c; 编译 2.1 不带Tensile的编译 如果是在conda环境中&#xff0c;需要deactive conda 环境…

线上商城做活动,页面氛围布置不能少

一个商城系统要做营销&#xff0c;该从哪些方面入手营造商城活动氛围&#xff0c;对于线上商城系统来说&#xff0c;除了营销的价格氛围&#xff0c;另一个重要的氛围就是视觉氛围&#xff0c;能让人第一眼注意到&#xff0c;并产生兴趣&#xff0c;这就迈出了营销的关键一步。…

《springcloud alibaba》 五 gateway网关

目录 gateway基础版本pom.xmlapplication.yml启动类测试 gateway集成nacosorder-nacos和stock-nacos项目微调cloud-gateway调整测试 gateway集成nacos简写版本内置断言自定义断言工厂规范 全局过滤器gateway流控降级pom.xmlapplication.yml测试流控具体配置api流控 降级代码版本…

数字社交的新典范:解析Facebook的成功密码

在当今数字化时代&#xff0c;社交媒体已经成为人们日常生活的重要组成部分&#xff0c;而Facebook作为最知名的社交媒体平台之一&#xff0c;其成功之处备受瞩目。本文将深入解析Facebook的成功密码&#xff0c;探讨其在数字社交领域的新典范。 1. 用户体验的优化 Facebook注…

Dude, where’s that IP? Circumventing measurement-based IP geolocation(2010年)

下载地址:https://www.usenix.org/legacy/event/sec10/tech/full_papers/Gill.pdf 被引次数:102 Gill P, Ganjali Y, Wong B. Dude, Wheres That {IP}? Circumventing Measurement-based {IP} Geolocation[C]//19th USENIX Security Symposium (USENIX Security 10). 2010.…

UE_导入内容_Maya静态网格体导出为FBX的常规设置

注意事项&#xff1a;单位设置统一为cm&#xff1b;轴朝向&#xff0c;Maya默认y轴朝上&#xff0c;UE4 z轴向上&#xff1b;变换枢轴&#xff0c;UE4会将导入模型前世界中心作为枢轴中心&#xff0c;要旋转就需要注意了&#xff1b;法线&#xff0c;UE4内材质默认单面显示&…

ubuntu 更改 ssh 默认端口

出于加固安全考虑&#xff0c;一般公司会禁用 ssh 的 22 端口号&#xff0c;因此我们需要改为其他端口。 1、ssh 命令行登录 进入台式机&#xff0c;修改 /etc/ssh/sshd_config 文件中的 Port 配置行&#xff0c;将 22 改为 8022&#xff0c;保存修改后&#xff0c;重启 ssh 服…

MySQL 主从 AUTO_INCREMENT 不一致问题分析

作者&#xff1a;vivo 互联网数据库团队 - Wei Haodong 本文介绍了 MySQL5.7 中常见的replace into 操作造成的主从auto_increment不一致现象&#xff0c;一旦触发了主从切换&#xff0c;业务的正常插入操作会触发主键冲突的报错提示。 一、问题描述 1.1 问题现象 在 MySQL …