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-06
Java求解兩個(gè)非負(fù)整數(shù)最大公約數(shù)算法【循環(huán)法與遞歸法】
這篇文章主要介紹了Java求解兩個(gè)非負(fù)整數(shù)最大公約數(shù)算法,結(jié)合實(shí)例形式分析了java求解最大公約數(shù)的實(shí)現(xiàn)方法,并附帶了循環(huán)法與遞歸法算法思路,需要的朋友可以參考下2018-03-03
Java動(dòng)態(tài)編譯執(zhí)行代碼示例
這篇文章主要介紹了Java動(dòng)態(tài)編譯執(zhí)行代碼示例,具有一定借鑒價(jià)值,需要的朋友可以參考下。2017-12-12
Spring AOP + 注解實(shí)現(xiàn)統(tǒng)一注解功能
本文我們通過Spring AOP和Java的自定義注解來實(shí)現(xiàn)日志的插入功能,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友一起看看吧2018-05-05
idea如何關(guān)閉頁面顯示的瀏覽器圖標(biāo)
這篇文章主要介紹了idea如何關(guān)閉頁面顯示的瀏覽器圖標(biāo)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07
Java+Appium實(shí)現(xiàn)屏幕錄制功能
這篇文章主要介紹了Java如何利用Appium實(shí)現(xiàn)屏幕錄制功能,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-06-06
java數(shù)據(jù)結(jié)構(gòu)圖論霍夫曼樹及其編碼示例詳解
這篇文章主要為大家介紹了java數(shù)據(jù)結(jié)構(gòu)圖論霍夫曼樹及其編碼示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪2021-11-11

