Java使用Swing實(shí)現(xiàn)一個(gè)模擬電腦計(jì)算器
自己寫了一個(gè)計(jì)算器類似效果如下:
直接上源碼,后上講解。
一、源碼
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","X2","√x","÷","7","8","9", "X","4","5","6","-","1","2","3","+","+/-","0",".","="};//計(jì)算器的功能鍵保存 private JButton [] buttons=new JButton[keys.length];//創(chuàng)建按鈕 private JTextField resultText=new JTextField("0");//結(jié)果保存用于在計(jì)算器上顯示 private double resultNum =0.0000;//用于保存運(yùn)算的結(jié)果 private boolean firstDigit=true;//判斷是否是第一個(gè)輸入的數(shù)字,或者是運(yùn)算符后第一個(gè)數(shù)字 private String operate ="=";//記錄當(dāng)前的運(yùn)算符 private boolean opearteValidFlag =true;//判斷當(dāng)前輸入是否合法 //構(gòu)造函數(shù) public MyCalculator(){ frame.setLocation(300,200); frame.setSize(new Dimension(366,439)); frame.setVisible(true); frame.setResizable(true);//窗口大小可修改 //這里采用awt組件來關(guān)閉窗口 事件監(jiān)聽 frame.addWindowListener(new WindowAdapter() { @Override public void windowClosed(WindowEvent e) { System.exit(0); } }); } public void init(){ //先定義三種顏色 用于背景板的填充 數(shù)值為網(wǎng)上查找 Color c1=new Color(181,181,181); Color c2=new Color(126,192,238); Color c3=new Color(232,232,232); //計(jì)算器功能面板初始化 JPanel pText =new JPanel();//用于保存文本域 JPanel pKey =new JPanel();//用于保存功能按鍵 //對(duì)文本域進(jìn)行初始化 pText.setLayout(new BorderLayout()); pText.add(resultText); resultText.setFont(new Font("楷體",Font.BOLD,43));//設(shè)置文本框中字體的格式 resultText.setHorizontalAlignment(JTextField.RIGHT);//文本框默認(rèn)右對(duì)齊 resultText.setEditable(false);//文本域不可編輯 resultText.setBorder(null);//設(shè)置邊框?yàn)闊o resultText.setBackground(c1); //對(duì)功能案件進(jìn)行初始化 pKey.setLayout(new GridLayout(6,4,2,2)); //六行四列,相鄰兩個(gè)按鈕上下間隔均為兩個(gè)像素 //開始在按鍵區(qū)加入前八個(gè)功能鍵 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);//設(shè)置無邊框 buttons[i].addActionListener(myActionListener);//添加監(jiān)聽器 } 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);//設(shè)置無邊框 buttons[i].addActionListener(myActionListener);//添加監(jiān)聽器 } //最后將=號(hào)的背景色改為藍(lán)色,也就是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(); //對(duì)于具有清除刪除功能按鍵的處理(CE C BACK) if(key.equals(keys[1])||key.equals(keys[2])||key.equals(keys[3])){ doDeleteKey(key); } //對(duì)只需要一個(gè)數(shù)值的按鍵處理(% 1/x x2 √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); } //對(duì)需要兩個(gè)數(shù)值的按鍵的處理(÷ 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); } //對(duì)數(shù)字按鍵進(jìn)行處理(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)); //如果內(nèi)容長(zhǎng)度大于1,那么直接刪掉最后一個(gè)字符 }else{ //內(nèi)容長(zhǎng)度等于1 resultText.setText("0"); firstDigit=true; } } } private void doOperator1(String key){ //對(duì)只需要一個(gè)數(shù)值的按鍵處理(% 1/x x2 √x +/- ) operate=key; if(operate.equals("%")){ resultNum=getNumFromText()/100; } else if(operate.equals("1?x")){ if(getNumFromText()==0){ //System.out.println("0沒有倒數(shù)!"); resultText.setText("零沒有倒數(shù)!"); opearteValidFlag=false; }else{ resultNum=resultNum+1.0/getNumFromText(); } } else if(operate.equals("√x")){ if(getNumFromText()<0){ //System.out.println("負(fù)數(shù)不能開方!"); resultText.setText("負(fù)數(shù)不能開方!"); opearteValidFlag=false; }else{ resultNum=resultNum+Math.sqrt(getNumFromText()); } } else if(operate.equals("X2")){ resultNum=resultNum+getNumFromText()*getNumFromText(); } else if(key.equals("+/-")){ resultNum=-getNumFromText(); firstDigit=true; opearteValidFlag=true; } } //兩個(gè)數(shù)進(jìn)行運(yùn)算 ÷ X - + = private void doOperator2(String key){ if(operate.equals("÷")){ if(getNumFromText()==0){ //System.out.println("零不能做除數(shù)!"); resultText.setText("零不能做除數(shù)!"); 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){ //如果是第一個(gè)輸入的數(shù)字或者符號(hào)后第一個(gè)數(shù)字 if(firstDigit){ if(key.equals(".")) /*resultText.setText(resultText.getText()+".");*/{ //上來直接按. if(resultNum==0&&operate=="=") resultText.setText(resultText.getText()+"."); //上來先按了個(gè)別的運(yùn)算符 在按. else{ resultText.setText("0."); // resultText.setText("出錯(cuò)!"); //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、創(chuàng)建我們所需的變量
計(jì)算器上的按鍵不少,我們都定義在一個(gè)keys數(shù)組當(dāng)中,并且初始化一個(gè)buttons按鈕數(shù)組。
除了我們的按鈕之外,還有我們的輸出顯示窗口resultText,輸出的結(jié)果我們都用resultNum來記錄,之后在放到我們的輸出窗口上。
其他的都寫成注解了。
private JFrame frame=new JFrame("CSDN--哈__"); private String[] keys = {"%","C","CE","Back","1?x","X2","√x","÷","7","8","9", "X","4","5","6","-","1","2","3","+","+/-","0",".","="};//計(jì)算器的功能鍵保存 private JButton [] buttons=new JButton[keys.length];//創(chuàng)建按鈕 private JTextField resultText=new JTextField("0");//結(jié)果保存用于在計(jì)算器上顯示 private double resultNum =0.0000;//用于保存運(yùn)算的結(jié)果 private boolean firstDigit=true;//判斷是否是第一個(gè)輸入的數(shù)字,或者是運(yùn)算符后第一個(gè)數(shù)字 private String operate ="=";//記錄當(dāng)前的運(yùn)算符 private boolean opearteValidFlag =true;//判斷當(dāng)前輸入是否合法
2.面板初始化
面板初始化就是init方法,注釋我都寫了,這里不在講了,也沒啥重要的,就是美化一下面板。
3.添加按鈕事件監(jiān)聽機(jī)制
當(dāng)我們點(diǎn)擊計(jì)算機(jī)上的按鈕的時(shí)候,計(jì)算器要給出反饋,這時(shí)就需要我們添加一個(gè)事件監(jiān)聽機(jī)制了。注釋寫好了,當(dāng)我們點(diǎn)擊不同的按鈕的時(shí)候要處理不同的功能。
public class MyActionListener implements ActionListener{ @Override public void actionPerformed(ActionEvent e) { String key = e.getActionCommand(); //對(duì)于具有清除刪除功能按鍵的處理(CE C BACK) if(key.equals(keys[1])||key.equals(keys[2])||key.equals(keys[3])){ doDeleteKey(key); } //對(duì)只需要一個(gè)數(shù)值的按鍵處理(% 1/x x2 √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); } //對(duì)需要兩個(gè)數(shù)值的按鍵的處理(÷ 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); } //對(duì)數(shù)字按鍵進(jìn)行處理(1 2 3 4 5 6 7 8 9 .) else{ doNumberKey(key); } } }
4.處理對(duì)于具有清除刪除功能按鍵的處理(CE C BACK)
計(jì)算器上有個(gè)清空按鍵C大家都用過吧,點(diǎn)了這個(gè)C之后我們所有的輸入都會(huì)被初始化。倘若點(diǎn)了退格鍵那我們就把面板上的文字域刪掉一個(gè)符號(hào)。比如我們輸入的是111,點(diǎn)了退格之后就是11,當(dāng)然你會(huì)想這只是文字域的變化,那我們保存的要計(jì)算的值為什么不變?別著急,真正開始計(jì)算是在我們點(diǎn)擊了加減乘除這一類的符號(hào)的時(shí)候才會(huì)從面板讀取值的。
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)); //如果內(nèi)容長(zhǎng)度大于1,那么直接刪掉最后一個(gè)字符 }else{ //內(nèi)容長(zhǎng)度等于1 resultText.setText("0"); firstDigit=true; } } }
5.兩個(gè)數(shù)進(jìn)行運(yùn)算加減乘除
上來先判斷你當(dāng)前的的符號(hào)是什么,并且也進(jìn)行了一些錯(cuò)誤情況的判斷,如除數(shù)不能為0什么的。
下邊你就能看到我們的resultNum被使用了。最后來個(gè)操作是否合法判斷,如果合法并且輸出結(jié)果最后是0那我們直接就把0輸出到面板上,但是倘若我們的輸出結(jié)果有精度差,那我們就得自己將0放到面板上了。
注:我使用的浮點(diǎn)數(shù)計(jì)算并不是BigDecimal,所以存在精度差。
private void doOperator2(String key){ if(operate.equals("÷")){ if(getNumFromText()==0){ //System.out.println("零不能做除數(shù)!"); resultText.setText("零不能做除數(shù)!"); 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; }
到此這篇關(guān)于Java使用Swing實(shí)現(xiàn)一個(gè)模擬計(jì)算器的文章就介紹到這了,更多相關(guān)Java Swing模擬計(jì)算器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot中使用HTTP客戶端工具Retrofit
這篇文章主要為大家介紹了SpringBoot中使用HTTP客戶端工具Retrofit方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06Java求解兩個(gè)非負(fù)整數(shù)最大公約數(shù)算法【循環(huán)法與遞歸法】
這篇文章主要介紹了Java求解兩個(gè)非負(fù)整數(shù)最大公約數(shù)算法,結(jié)合實(shí)例形式分析了java求解最大公約數(shù)的實(shí)現(xiàn)方法,并附帶了循環(huán)法與遞歸法算法思路,需要的朋友可以參考下2018-03-03Java動(dòng)態(tài)編譯執(zhí)行代碼示例
這篇文章主要介紹了Java動(dòng)態(tài)編譯執(zhí)行代碼示例,具有一定借鑒價(jià)值,需要的朋友可以參考下。2017-12-12Spring AOP + 注解實(shí)現(xiàn)統(tǒng)一注解功能
本文我們通過Spring AOP和Java的自定義注解來實(shí)現(xiàn)日志的插入功能,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友一起看看吧2018-05-05idea如何關(guān)閉頁(yè)面顯示的瀏覽器圖標(biāo)
這篇文章主要介紹了idea如何關(guān)閉頁(yè)面顯示的瀏覽器圖標(biāo)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07Java+Appium實(shí)現(xiàn)屏幕錄制功能
這篇文章主要介紹了Java如何利用Appium實(shí)現(xiàn)屏幕錄制功能,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-06-06java數(shù)據(jù)結(jié)構(gòu)圖論霍夫曼樹及其編碼示例詳解
這篇文章主要為大家介紹了java數(shù)據(jù)結(jié)構(gòu)圖論霍夫曼樹及其編碼示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪2021-11-11