Android學習之計算器app(java + 詳細注釋 + 源碼)

運行結果:

基礎的四則運算:

可能會出現的問題以及解決方法:

?問題1:出現多個操作符。

例子:1++++++2

解決方法:

在用戶點擊操作符之后,去檢查之前的最后一位,如果最后一位也是操作符的話,就進行替代操作。

問題2:小數點問題。

例子:0......1? 以及 .2

解決方法:

對于0.....1的問題,用的是一個全局變量 addPoint,當它為true的時候才可以進行添加小數點操作。

當點擊 π 或者是 小數點之后 就要把 addPoint 置為false,也即表示不能再去添加小數點了。

當點擊操作符或者是C(清空)之后就要把 addPoint 置為false,也即表示可以再去添加小數點了。

問題3:非法操作。

例子:

1:除0

2:階乘溢出

3:負數開根號

4:logx, 其中x <= 0

5:(0.123)!

6:(-3)!

解決方法:

對每個運算進行提前監控,如果出現違規操作要把用戶的除了C(清空)按鈕外全部禁掉,然后做出違規提示,參考Win11自帶計算器。但是感覺更加規范的是 可以自定義異常 然后去對應到每一個的異常處理問題。

問題4:負數的復雜性

例子:-3 對這個實現起來還是比較麻煩的

解決方法:

對這個不進行特殊判斷,還是點擊 "-" 之后看看它的前面有沒有數字,如果沒有的話,也去補上0, 這個0是默認的。

新增括號功能:

對括號進行了顯示,以及可以進行括號運算

在界面顯示出右括號和左括號的數量,而且右括號的數量數不能多于左括號的,參照win11自帶計算器。

可能出現的問題以及解決方法:

問題1:出現 (+)。

也即是括號里面只有操作符。

解決的方法:

1:當點擊運算符的時候,檢查它的前面是不是 "(", 如果是的話就去自動去補0

2:當點擊 "(" 的時候,去檢查它的前面是不是 操作符,如果是的話就去自動補0

問題2:出現(0)(0)這樣的情況。
解決方法:

當用戶點擊 "(" 的時候去校驗當前已經存在的字符串的最后一位,如果它不是操作符的話,就去指定去補上一個操作符,我在這里默認的是 "x"。

問題3:出現0 + (-3) + 5 這樣的情況。
解決方法:

當用戶點擊操作符的時候,就去檢測當前已經存在的最后一個字符是不是數字,如果不是數字的話,就去補上一個默認的0,但是還會出現這樣的情況0 + (0 - 3) 0 + 3,它把0補到了這里了,這里再去加一個特殊的判斷,如果最后一個是 ")" 就不去加上這個默認的0。但是改為之后又出現了這樣的情況:0+(0)------------,解決的方法當這個最后一個字符是 "(" 的時候再去增加默認的0。??

聲明:

因為作者是一個考研dog,so 沒有足夠的時間去寫這個,只能晚上10回去之后加班寫,或者在其他老師課上寫,因此間隔時間比較大,而且邏輯比較亂,希望大家多多包涵。?

計劃:

1:后期可以去增加一個 按鍵聲音的功能,也即是你點擊一個按鈕之后,就會產生特定的生硬,當然聲音是作者自己那美妙的聲音。(已經實現,用的是在線生成的ai女聲)。

2:增加登錄操作,把每個人的計算的操作給記錄下來,可以查看自己歷史計算記錄

java代碼:

package com.findyou.myapplication;import android.content.Context;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.SoundPool;
import android.os.Bundle;
import android.view.SoundEffectConstants;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;import java.math.BigInteger;
import java.util.HashMap;
import java.util.Objects;
import java.util.Stack;public class Test_jsq extends AppCompatActivity implements View.OnClickListener {private TextView tv_result, show_kh; // 獲取文本框的內容 為了進行設置// 第一個操作數// 第二個操作數// 運算符private String operator = "";// 結果private String result = "";// 顯示的文本內容 剛開始的時候要顯示的是 0private String showText = "0"; // 3+2private Boolean addPoint = true;private boolean denominatorIsZero = false; // 分母是否為0private final String ISZERO = "分母不可為0!";private final String FACTORIALERROR = "小數和分數沒有階乘,階乘只在自然數中進行";private final String OVERFLOW = "溢出";private final String NAGATIVE_HAS_NO_FACTORIAL = "負數沒有階乘";private final String NAGATIVE_HAS_NO_SQRT = "根號下要大于等于0";private final String LN_NEED_GREATER_THAN_ZERO = "ln里面需要大于0";private final String LON_NEED_GREATER_THAN_ZERO = "log里面需要大于0";// 新增加的 左右括號的顯示操作 初始化的括號的數量都顯示為 0private int leftParenthesis = 0, rightParenthesis = 0;// 以下是增加的聲音的功能// 定義一個全局的變量 看看用戶想不想去播放音效private Boolean play = true; // 表示的是 可以去播放音效private int currentId; // 為了記錄當前點擊了那個聲音了,是為了方便后面的暫停SoundPool sp; // 聲明SoundPool的引用HashMap<String, Integer> hm; // 聲明HashMap來存放聲音文件@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_calculator);initSoundPool(); // 初始化聲音池的方法// 獲取tv_result ctrl + alt + f 變為全局變量tv_result = findViewById(R.id.tv_result);show_kh = findViewById(R.id.show_kh); // 對括號的截取和顯示Button btn_cancel = findViewById(R.id.btn_cancel);btn_cancel.setOnClickListener(this);Button btn_sy = findViewById(R.id.sy);btn_sy.setOnClickListener(this);// 給每個按鈕設置監聽findViewById(R.id.btn_cancel).setOnClickListener(this);findViewById(R.id.btn_divide) .setOnClickListener(this);//“除法"按鈕findViewById(R.id.btn_multiply).setOnClickListener(this); // "乘法"按鈕findViewById(R.id.btn_clear) .setOnClickListener(this);findViewById(R.id.btn_seven).setOnClickListener(this); // 數字7findViewById(R.id.btn_eight).setOnClickListener(this); // 數字8findViewById(R.id.btn_nine).setOnClickListener(this); // 數字9findViewById(R.id.btn_plus) .setOnClickListener(this) ;findViewById(R.id.btn_four).setOnClickListener(this); // 數字4findViewById(R.id.btn_five).setOnClickListener(this); // 數字5findViewById(R.id.btn_six) .setOnClickListener(this); // 數字6findViewById(R.id.btn_minus).setOnClickListener(this);// "減法"按鈕findViewById(R.id.btn_one).setOnClickListener(this); // 數字1findViewById(R.id.btn_two).setOnClickListener(this); // 數字2findViewById(R.id.btn_three).setOnClickListener(this); // 數字3findViewById(R.id.btn_reciprocal).setOnClickListener(this);// 求倒數按鈕findViewById(R.id.btn_zero).setOnClickListener(this); // 數字0findViewById(R.id.btn_dot).setOnClickListener(this);// “小數點"按鈕findViewById(R.id.btn_equal).setOnClickListener(this);// "等號"按鈕findViewById(R.id.btn_sqrt) .setOnClickListener(this) ;// 開根號按鈕findViewById(R.id.btn_PI).setOnClickListener(this); // π按鈕的監聽findViewById(R.id.btn_factorial).setOnClickListener(this); // 階乘按鈕的監聽findViewById(R.id.btn_e).setOnClickListener(this); // e 按鈕的監聽findViewById(R.id.btn_abs).setOnClickListener(this); // 絕對值 按鈕的監聽// 新增加的功能findViewById(R.id.btn_left_kh).setOnClickListener(this); // 對左括號 按鈕進行監聽findViewById(R.id.btn_right_kh).setOnClickListener(this); // 對右括號 按鈕進行監聽findViewById(R.id.btn_log).setOnClickListener(this); // 對 log 按鈕 進行監聽findViewById(R.id.btn_ln).setOnClickListener(this); // 對 ln 按鈕進行監聽}// 變為公用的@Overridepublic void onClick(View v) {if(v.getId() == R.id.sy) {if(play) { // 要去關閉聲音了findViewById(R.id.sy).setBackground(ContextCompat.getDrawable(this, R.drawable.close));play = false;} else {findViewById(R.id.sy).setBackground(ContextCompat.getDrawable(this, R.drawable.open));play = true;}return;}// 測試 是否能正常顯示在界面 很好奇 為什么這個 測試的 沒有 ban 掉// tv_result.setText(((TextView) v).getText().toString());String inputText;// 如果是開根號的按鈕if (v.getId() == R.id.btn_sqrt) {inputText = "√";} else {inputText = ((TextView) v).getText().toString();}if(sp != null && currentId != 0) {sp.stop(currentId); // 立馬停止當前正在播放的聲音}if(play && !inputText.equals("=")) {// 點擊之后 開始在這里播放音樂playSound(inputText);}int t = v.getId();// 點擊了清空按鈕if (t == R.id.btn_clear) {// 清空的時候 要去恢復按鈕illegal(true);// 注意二者順序clear();// 也要去清空括號clearKh();} else if(t ==  R.id.btn_cancel) { // 后退按鈕// 注意 后退 是 不能 去進行 后退 操作符號 的showText = Backoff(showText);if(Objects.equals(showText, "")) {showText = "0"; // 最后一個都被清空了}// 刷新文本refreshText(showText);} else if(t == R.id.btn_plus || t == R.id.btn_minus || t == R.id.btn_multiply || t == R.id.btn_divide){ // 點擊了 加 減 乘 除//  如果操作符的前面是小數點的話 就要把小數點給省略掉 0.1 - 0. + ---> 0.1 - 0 +addPoint = true; // 把小數點可以更新了operator = inputText;char temp = showText.charAt(showText.length() - 1);// 每當進行 加減操作的時候 先去看看它的最后一個是不是有效的 不是有效的話 要去主動去增加一個 0  無論是小數點還是普通的加減// 增加的 這一個 可能出現了問題了//            if(!checkIsNum(showText.charAt(showText.length() - 1)) && temp != '(' && temp != ')') {
//                showText = showText + "0";
//            }// 這里防止出現這樣的情況: (+0)的情況
//            if(checkIskh(temp)) {
//                showText = showText + "0";
//            }// 檢查前面的最后一項是不是數字 如果不是數字的話 就去補上一個默認的0if(!checkIsNum(temp) && temp != ')' && !checkIsOp(temp)) {showText += "0";}// 查看當前這個字符串的最后一個 也是操作符的話 就把它給覆蓋掉if(checkIsOp(temp)) {// 就把當前的字符串的最后一個給替換掉showText = showText.substring(0, showText.length() - 1) + operator;refreshText(showText);} else {// 這里解決的是 0.-3 這樣的問題 解決的方法是把 小數點給去掉if(showText.charAt(showText.length() - 1) == '.') {showText = showText.substring(0, showText.length() - 1);}refreshText(showText + operator);}//  等號 的操作} else if(t == R.id.btn_equal) { // 等號按鈕// 進行規格化String ret = Normalized(js(showText));refreshText(ret);// 計算的結果要去循環的去播放出來playRet(ret);// 前提是沒有小數點的話 再去恢復if(!ret.contains(".")) {// 等號的話 也要去恢復小數點的操作addPoint = true;}clearKh();// 然后去清空掉
//            showText = "0";//1 + 0123.0 √} else if(t == R.id.btn_sqrt) { // 開根號js3(1); // 1 表示的是開根號的操作} else if(t == R.id.btn_reciprocal) { // 求倒數js3(2);} else if(t == R.id.btn_PI)  { // 點擊了 π 的 操作js3(4);} else if(t == R.id.btn_factorial) { // 點擊了階乘的操作js3(3);} else if(t == R.id.btn_abs) {js3(5); // 點擊了絕對值的操作} else if(t == R.id.btn_e) { // 點擊的是 e 的 操作js3(6);} else if(t == R.id.btn_ln) { // 點擊的是 ln 的操作js3(7);} else if(t == R.id.btn_log) { // 點擊的是 log 的操作js3(8);}else if(t == R.id.btn_left_kh) {leftParenthesis ++ ;// 刷新 界面的括號顯示數字 并且把 括號給拼接上去// 這里也要特判一下 可能存在 這樣的情況 比如: (0)() 要把它變成 (0)x(0) 這樣的情況char pre = showText.charAt(showText.length() - 1);if(pre == ')') {showText += 'x';}// 這里需要去校驗一種情況是 1( 要把它變為 1 + (這樣的形式if(checkIsNum(pre)) {showText += "+";}refreshText(showText + inputText);} else if(t == R.id.btn_right_kh) { // 點擊了右括號// 為了讓他們進行匹配 也即是 存在 對應的左括號的時候才進行匹配if(rightParenthesis < leftParenthesis) {rightParenthesis ++ ;// 刷新 界面的右括號顯示數字 并且把括號給拼接上去// 這里要單獨去檢驗一下 可能是 () 這樣的情況是不允許的 要去在左括號的后面去拼接一個 0char pre = showText.charAt(showText.length() - 1);if(pre == '(') {showText += "0";}// 這里也要去防止 (0+)這樣的情況if(checkIsOp(pre)) {showText += "0"; // 去給它去補上 0}refreshText(showText + inputText);}}else  {// 點擊了 數字 和 小數點// 這里要去監控 如果之前點擊了小數點 這里的話 就不能再去進行拼接了if(inputText.equals(".")) {// 這里可能會出現很多的 小數點 例如: 0.000.if(!addPoint || getLastNumber(showText).contains(".")) { // 表示不可以去添加小數點refreshText(showText); // 保持原來的return ;} else {// 這里要去判斷一下 小數點的前方是否為操作符 如果是的話 就自動拼接一個 0char pre = showText.charAt(showText.length() - 1);if(checkIsOp(pre) || checkIskh(pre)) {showText = showText + "0";}refreshText(showText + inputText); // 保持原來的addPoint = false;return;}}char pre = showText.charAt(showText.length() - 1);// 如果前面不是數字的話 要去自動補上加號if(pre == ')') {showText += "+";}refreshText(showText + inputText); // 拼接}}/*** 播放音樂的* @param inputText*/private void playSound(String inputText) {// 在這里Debug一下//  Toast.makeText(this, "點擊了" + inputText, Toast.LENGTH_SHORT).show();playSoundMain(inputText, 0); // 默認都是單循環的}/*** 主要的聲音播放方法* @param sound map里面的key* @param loop 表示循環的次數*/private void playSoundMain(String sound, int loop) {if (sp == null || hm.get(sound) == null) {Toast.makeText(this, "音頻資源未加載或無效", Toast.LENGTH_SHORT).show();return;}// 獲取AudioManager引用AudioManager am = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);// 獲取當前音量float streamVolumeCurrent = am.getStreamVolume(AudioManager.STREAM_MUSIC);// 獲取系統最大音量float streamVolumeMax = am.getStreamMaxVolume(AudioManager.STREAM_MUSIC);// 計算得到播放音量float volume = streamVolumeCurrent / (float) streamVolumeMax;// 調用SoundPool的play方法來播放聲音文件currentId = sp.play(hm.get(sound), volume, volume, 1, loop, 1.0f);}/*** 計算的是 開根號 倒數 階乘 π e* @param num 約定好的標志*            1:開根號*            2:倒數*            3:階乘*            4:π*            5:絕對值*            6:e*            7:ln*/private void js3(int num) {String snum = getLastNumber(showText);String newNumber = "";if(num == 1) { // 開根號if(Double.parseDouble(snum) < 0) {abnormal(NAGATIVE_HAS_NO_SQRT);return;}newNumber = String.valueOf(Math.sqrt(Double.parseDouble(snum)));} else if(num == 2) { // 倒數的操作// 先去檢查分母是不是為0的if(Double.parseDouble(snum) - 0.0 == 0) {abnormal(ISZERO); // 分母不可為 0return ;}addPoint = false; // 不能再去增加小數點了// 開始邏輯上的計算newNumber = String.valueOf(1.0 / Double.parseDouble(snum));} else if(num == 3) { // 階乘// 注意:小數和分數沒有階乘 階乘法只在自然數中進行if(!addPoint || showText.contains(".")) {// 表示當前是增加了小數的 是不能去進行階乘的運算的abnormal(FACTORIALERROR);return; // 這個return 是為了防止 其他信息 的覆蓋} else { // 表示當前是沒有小數的 是可以進行階乘的if(Integer.parseInt(snum) > 100) {abnormal(OVERFLOW); // 階乘太大會導致溢出return ;} else if(Integer.parseInt(snum) < 0 ) {abnormal(NAGATIVE_HAS_NO_FACTORIAL); // 負數沒有階乘return;}newNumber = factorial(Integer.parseInt(snum));}} else if(num == 4) { //πaddPoint = false; // 注意 點擊了PI 之后也要去限制小數點的newNumber = String.valueOf(Math.PI);} else if(num == 5) { // 絕對值的操作// 感覺這個絕對值 有點雞肋if(Double.parseDouble(snum) < 0 ) {newNumber = snum.substring(1); // 把前面的符號給截取掉} else {// 但是這個新的 還要去規范一下 不能把前置 0 給顯示newNumber = cancelZero(snum); // 不進行截取}} else if(num == 6) { // e 2.71828newNumber = String.valueOf(Math.E);} else if(num == 7) { // ln 的操作if(Double.parseDouble(snum) <= 0) {abnormal(LN_NEED_GREATER_THAN_ZERO);return ;}newNumber = String.valueOf(Math.log(Double.parseDouble(snum)));} else if(num == 8) { // log 的操作if(Double.parseDouble(snum) <= 0) {abnormal(LON_NEED_GREATER_THAN_ZERO);return ;}newNumber = String.valueOf(Math.log10(Double.parseDouble(snum)));}// 我需要找到最后這個的位置// over: 獲得這個的num的位置 然后進行替換 把老的替換為新的// 我需要去找到 最后一個操作符的位置int pos = getLastOperatorPose(showText);// 開始進行替代 注意的是 這里的 substring 第二個參數表示的最后的位置 注意是 前閉后開的showText = showText.substring(0, pos + 1);char temp = showText.charAt(showText.length() - 1);// 如果最后一個不是運算符的話 就在去拼接一下加號 這個加號是默認的if(!checkIsOp(temp)) {showText += "+";}// 再去拼接新的showText = showText + newNumber;// 然后再去在界面進行顯示出來refreshText(showText);}/*** 清空括號 也即是下面這種情況* 1: 按下C的時候* 2: 等號的時候*/private void clearKh() {leftParenthesis = 0;rightParenthesis = 0;// 清空之后要去刷新 數量refreshText(showText);}/*** 對結果進行規格化* @param text 傳過來 需要規格化的數據*             例如: 00001 那么要返回的就是 1* @return*/private String cancelZero(String text) { // 取消前置無效0  以及后置無效0int j = 0;// 要對 test 進行校驗一個// 有哪些情況呢?// 1: 00008// 2: 0000.1for(int i = 0; i < text.length() - 1; i ++ ) {if(text.charAt(i) == '0' && (!checkIsOp(text.charAt(i + 1)) && text.charAt(i + 1) != '.' || text.charAt(i + 1) == ')' || text.charAt(i + 1) == '(')) {j = i + 1;} else {break;}}text = text.substring(j); // 從這里開始截取 并包括當前這個return text;}/*** 獲取 num 的 階乘的* @param num 想要獲取的 階乘的 num* @return*/private String factorial(int num) {// 為了解決階乘太大 用的是 BigIntegerBigInteger result = BigInteger.ONE; // 初始化為 1for (int i = 1; i <= num; i++) {result = result.multiply(BigInteger.valueOf(i)); // 逐步相乘}return String.valueOf(result); // 最后再去轉換為 string類型的 給進行輸出顯示}/*** 根據text 拋出指定的異常*/private void abnormal(String show) {// 要去禁用按鈕illegal(false);tv_result.setText(show);; // 并把錯誤的信息給顯示到文本框里面}/*** 后退按鈕的操作* @param t 出來的邏輯字符串* @return 返回的是 后退的字符串*/private String Backoff(String t) {for(int i = t.length() - 1; i >= 0; i -- ) {if(checkIsNum(t.charAt(i))) {// 需要注意的是 如果退的是 小數點的話 要求進行恢復if(t.charAt(i) == '.') {// 恢復 可以增加 小數點 的操作addPoint = true;}// 我就去后退一位return t.substring(0, i);} else {// 否則的話 就直接去回去的break;}}return t;}/*** 獲得最后一個操作符的位置* @param showText 傳來的字符串* @return 返回的是 最后一個操作符的位置* 例如: 1+2 返回的是1*/private int getLastOperatorPose(String showText) {int pos = -1;if(showText.charAt(0) == '-') {return pos;}for(int i = showText.length() - 1; i >= 0; i -- ) {if(checkIsOp(showText.charAt(i)) || checkIskh(showText.charAt(i))) { // 如果檢查發現是 操作符的話 就去返回它的下標 是包括它的return i;}}// 這個表示的是沒有操作符的return pos;}/*** 輸出結果的規格化* @param js* @return 返回的是 規格化之后的結果*/private String Normalized(double js) {// 是可以去進行規格化的if(js - (int)(js) == 0) {return String.valueOf((int)(js));} else {return String.valueOf(js);}}/*** 清空 并進行 初始化* 新增 對 小數點 的恢復*/private void clear() {// 清空的時候 注意把 小數點的功能也給進行恢復addPoint = true;refreshOperate("");refreshText("0"); // 0即表示為不存在 其實也是存在}// 刷新運算結果private void refreshOperate(String new_result) {result = new_result;operator = "";}/** 刷新 文本 的操作* 再去加上 輸出的校驗* */private void refreshText(String text) {String khNum = "左括號的數量: " + leftParenthesis + " 右括號的數量: " + rightParenthesis;// 這里在刷新的時候 也要把 括號的數量給顯示出來show_kh.setText(khNum);// 在刷新之前 對結果進行規格化一下 去除前置0的 那些沒有效的數據 但是要對小數進行特判text = cancelZero(text);showText = text; // 默認一直在拼接if(denominatorIsZero) { // 分母是否為0showText = ISZERO;}tv_result.setText(showText);// 對 等號 按鈕的監控if(leftParenthesis == rightParenthesis) {findViewById(R.id.btn_equal).setEnabled(true);} else {findViewById(R.id.btn_equal).setEnabled(false);}}/*** 主要的計算功能* @param s 傳過來的 字符串 要去計算的字符串 這里面沒有等號* @return*/private double js(String s) {// 第一個的 負數 是比較特殊的 要進行特判// 前面直接加上一個 0s = "0" + s;// 這里需要做一個判斷// 可能是-3 這樣的 但是返回的 也是-3 不要在進行計算下去了 這是一個獨特的
//        if(s.charAt(0) == '-') {
//            s = "0" + s;
//        } else if(Objects.equals(operator, "")) {
//            return Double.parseDouble(s);
//        }// 用到java里面的桟的算法// 存取的是 數字Stack<Double> number = new Stack<>();// 存取的是 操作符Stack<Character> op = new Stack<>();String t = "";for(int i = 0; i < s.length(); i ++ ) {char temp = s.charAt(i);// 如果當前這個 temp 是 運算符的話if(checkIsOp(temp) || temp == '(' || temp == ')') { // 如果當前這個是 運算符// 這樣的話 就需要把 字符串給轉換為 Double// 注意 放進去的前提是不為空的 把他放到 桟里面if(!t.isEmpty()) {number.push(Double.valueOf(t));}t = "";// 然后 看看 當前的字符是什么類型的if(temp == '+' || temp == '-') {while(!op.isEmpty()) {// 拿到桟頂元素char operator = op.peek();if(operator == '(') { // 左括號的優先級是 最低 的break;}op.pop();// 然后再從 整數桟里面 去拿出來兩個數 讓其進行計算// TODO: 這兩步數 是容易造成 error的 這點需要去著重的去關注double t1 = number.peek();number.pop();double t2 = number.peek();number.pop();// 注意的是 后 操作 前 的double ret = js2(t2, t1, operator);number.push(ret);}// 到這里的時候 就表示 op里面是空的了op.push(temp);} else if(temp == 'x' || temp == '÷') {// 當時 乘法或者是 除法的時候 要去校驗 它的下面是不是比它低的// 或者可以寫成 前提是不為空 然后 op.peek() == 'x' || op.peek() == '?'while(!op.isEmpty() && op.peek() != '+' && op.peek() != '-' && op.peek() != '(') {// 拿到桟頂元素char operator = op.peek();op.pop();// 然后再從 整數桟里面 去拿出來兩個數 讓其進行計算// TODO: 這兩步數 是容易造成 error的 這點需要去著重的去關注double t1 = number.peek();number.pop();double t2 = number.peek();number.pop();double ret = js2(t2, t1, temp);number.push(ret);}// 到這里的時候 是可以去當進去的op.push(temp);} else if(temp == ')') { // 這里對右括號單獨進行限制// 只要還沒遇到 左括號 就一直去把里面運算符的給彈出來 而且彈出來的時候 也把數字給彈出來兩個 然后和這個彈出來的運算符進行計算while(!op.isEmpty()) {char operator = op.peek();op.pop();if(operator == '(') {break; // 就匹配成功了}// 否則的話 就取出來兩個數字 然后把這個操作符 讓這兩個數進行運算的結果 放到存取數的桟里面// TODO: 但是這個的前提是存在的double t1 = number.peek();number.pop();double t2 = number.peek();number.pop();double ret = js2(t2, t1, operator);number.push(ret);}} else if(temp == '(') { // 左括號的話 直接 push 進去op.push(temp);}} else if(checkIsNum(temp)){ // 說明是 數字 或者是小數點t = t + temp;}}// Debug 了半天才發現是這里出現了問題 我也是服了if(!t.isEmpty()) {// 注意在 類型轉換的時候 看看是不是為空的 因為空的話 是不能去進行轉換的number.push(Double.valueOf(t));}// 開始計算while (number.size() > 1) {// 這里 沒有運算符 也是很致命的if(op.isEmpty()) {break;}double t1 = number.peek();number.pop();double t2 = number.peek();number.pop();number.push(js2(t2, t1, op.peek()));op.pop();}operator = "";return number.peek();}/*** 計算  + - * / 的* @param t1* @param t2* @param temp* @return*/private double js2(double t1, double t2, char temp) {if(temp == '+') {return t1 + t2;}if(temp == '-') {return t1 - t2;}if(temp == 'x') {return t1 * t2;}if(temp == '÷') {// 出現了 分母為0if(t2 == 0 ) {abnormal(ISZERO); // 分母不可為0 && 限制按鈕的點擊}return t1 / t2;}return 0.0; // 這個是假的}/*** 檢查 是不是操作符* @param t* @return*/private Boolean checkIsOp(Character t) {return t == '+' || t == '-' || t == '÷' || t == 'x';}/*** 檢查是不是 數字 這里把小數點也認為是數字了* @param t* @return*/private Boolean checkIsNum(Character t) {return (t >= '0' && t <= '9') || t == '.';}/*** 獲得字符串 最后 一個 數字* @param s* @return*/private String getLastNumber(String s) {String ret = "";if(s.charAt(0) == '-') { // 表示的是負數ret = s;} else {for(int i = s.length() - 1; i >= 0; i -- ) {if(checkIsNum(s.charAt(i))) {ret = s.charAt(i) + ret;} else {break;}}ret = "0" + ret;}// 這個去解決的是 1233 + 也即是最后一個不是數字if(ret.contains(".")) { // 這個的目的是為了 防止 出現小數點之后 沒有出現數字的情況 比如: 123.ret = ret + "0";}return ret;}/*** 去檢查這個 t 是不是括號 因為要為括號進行特殊的操作* @param t* @return*/private boolean checkIskh(char t) {return t == '(' || t == ')';}// 封掉所有的按鈕 單獨剩下一個 清空的按鈕 要去做出適當的提示// 表示的是 不合法 把全部的按鈕全都給禁用了 除了 Cprivate void illegal(boolean value) {denominatorIsZero = !value;findViewById(R.id.btn_cancel).setEnabled(value);findViewById(R.id.btn_divide).setEnabled(value);findViewById(R.id.btn_multiply).setEnabled(value);findViewById(R.id.btn_clear).setEnabled(true); // 這個是特殊的findViewById(R.id.btn_seven).setEnabled(value);findViewById(R.id.btn_eight).setEnabled(value);findViewById(R.id.btn_nine).setEnabled(value);findViewById(R.id.btn_plus).setEnabled(value);findViewById(R.id.btn_four).setEnabled(value);findViewById(R.id.btn_five).setEnabled(value);findViewById(R.id.btn_six).setEnabled(value);findViewById(R.id.btn_minus).setEnabled(value);findViewById(R.id.btn_one).setEnabled(value);findViewById(R.id.btn_two).setEnabled(value);findViewById(R.id.btn_three).setEnabled(value);findViewById(R.id.btn_reciprocal).setEnabled(value);findViewById(R.id.btn_zero).setEnabled(value);findViewById(R.id.btn_dot).setEnabled(value);findViewById(R.id.btn_equal).setEnabled(value);findViewById(R.id.btn_sqrt).setEnabled(value);// 新增的 限制按鈕findViewById(R.id.btn_PI).setEnabled(value);findViewById(R.id.btn_factorial).setEnabled(value);findViewById(R.id.btn_e).setEnabled(value);findViewById(R.id.btn_abs).setEnabled(value);// 新增的 限制按鈕findViewById(R.id.btn_log).setEnabled(value);findViewById(R.id.btn_ln).setEnabled(value);findViewById(R.id.btn_left_kh).setEnabled(value);findViewById(R.id.btn_right_kh).setEnabled(value); // 對右括號 按鈕進行監聽}/*** 播放最后的運算結果* @param ret*/private void playRet(String ret) {// 先去播放一個等號playSound("=");// 這里是循環播放的答案for(int i = 0; i < ret.length(); i ++ ) {// 播放playSound(ret.charAt(i) + "");}}/*** 聲音池的 初始化 init*/private void initSoundPool() {// 初始化聲音池sp = new SoundPool.Builder().setMaxStreams(4).setAudioAttributes(new AudioAttributes.Builder().setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).setUsage(AudioAttributes.USAGE_MEDIA).build()).build();hm = new HashMap<String, Integer>(); // 創建HashMap對象// 加載聲音文件,并且設置為1號聲音放入hm中// 數字的聲音hm.put("1", sp.load(this, R.raw.one, 1));hm.put("2", sp.load(this,R.raw.two, 1));hm.put("3", sp.load(this,R.raw.three, 1));hm.put("4", sp.load(this,R.raw.four, 1));hm.put("5", sp.load(this,R.raw.five, 1));hm.put("6", sp.load(this,R.raw.six, 1));hm.put("7", sp.load(this,R.raw.seven, 1));hm.put("8", sp.load(this,R.raw.eight, 1));hm.put("9", sp.load(this,R.raw.nine, 1));hm.put("0", sp.load(this,R.raw.zero, 1));// 小數點的聲音hm.put(".", sp.load(this,R.raw.point, 1));// 操作符的聲音hm.put("=", sp.load(this,R.raw.equal, 1));hm.put("+", sp.load(this,R.raw.add, 1));hm.put("x", sp.load(this,R.raw.mut, 1));hm.put("÷", sp.load(this,R.raw.chu, 1));hm.put("-", sp.load(this,R.raw.jian, 1));hm.put("C", sp.load(this,R.raw.c, 1));hm.put("(", sp.load(this,R.raw.leftkh, 1));hm.put(")", sp.load(this,R.raw.rightkh, 1));// 運算操作hm.put("n!", sp.load(this,R.raw.jc, 1));hm.put("?", sp.load(this,R.raw.ht, 1));hm.put("π", sp.load(this,R.raw.pai, 1));hm.put("e", sp.load(this,R.raw.e, 1));hm.put("|x|", sp.load(this,R.raw.abs, 1));hm.put("1/x", sp.load(this,R.raw.ds, 1));hm.put("√", sp.load(this,R.raw.sqrt, 1));}
}

xml(界面)代碼:?

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/main"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:background="#EEEEEE"android:padding="5dp"><ScrollViewandroid:layout_width="match_parent"android:layout_height="wrap_content"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"><!--顯示簡單 計算器 字樣--><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:text="@string/simple_calculator"android:gravity="center"android:textColor="@color/black"android:textSize="20sp"/><TextViewandroid:id="@+id/show_kh"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="左括號數量為: 0  右括號數量為: 0"android:gravity="center"android:textColor="@color/black"android:textSize="20sp"/><!-- 計算機 文本的顯示--><TextViewandroid:id="@+id/tv_result"android:layout_width="match_parent"android:layout_height="wrap_content"android:background="@color/white"android:text="0"android:textColor="@color/black"android:lines="3"android:gravity="right|bottom"android:textSize="25sp"/><GridLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:columnCount="4"android:rowCount="7"><!--后退一個--><Buttonandroid:id="@+id/btn_cancel"android:layout_width="0dp"android:layout_height="@dimen/button_height"android:textSize="@dimen/button_font_size"android:layout_columnWeight="1"android:gravity="center"android:text="@string/cancel"android:textColor="@color/black"/><!--除法--><Buttonandroid:id="@+id/btn_divide"android:layout_width="0dp"android:layout_height="@dimen/button_height"android:textSize="@dimen/button_font_size"android:layout_columnWeight="1"android:gravity="center"android:text="@string/divide"android:textColor="@color/black"/><!--乘法--><Buttonandroid:id="@+id/btn_multiply"android:layout_width="0dp"android:layout_height="@dimen/button_height"android:textSize="@dimen/button_font_size"android:layout_columnWeight="1"android:gravity="center"android:text="@string/multiply"android:textColor="@color/black"/><!--清零操作--><Buttonandroid:id="@+id/btn_clear"android:layout_width="0dp"android:layout_height="@dimen/button_height"android:textSize="@dimen/button_font_size"android:layout_columnWeight="1"android:gravity="center"android:text="@string/clear"android:textColor="@color/black"/><!--新增的操作--><Buttonandroid:id="@+id/btn_PI"android:layout_width="0dp"android:layout_height="@dimen/button_height"android:textSize="@dimen/button_font_size"android:layout_columnWeight="1"android:gravity="center"android:text="@string/PI"android:textColor="@color/black"/><Buttonandroid:id="@+id/btn_e"android:layout_width="0dp"android:layout_height="@dimen/button_height"android:textSize="@dimen/button_font_size"android:layout_columnWeight="1"android:gravity="center"android:text="@string/e"android:textColor="@color/black"/><Buttonandroid:id="@+id/btn_abs"android:layout_width="0dp"android:layout_height="@dimen/button_height"android:textSize="@dimen/button_font_size"android:layout_columnWeight="1"android:gravity="center"android:text="@string/abs"android:textColor="@color/black"/><Buttonandroid:id="@+id/btn_factorial"android:layout_width="0dp"android:layout_height="@dimen/button_height"android:textSize="@dimen/button_font_size"android:layout_columnWeight="1"android:gravity="center"android:text="@string/factorial"android:textColor="@color/black"/><!--這里又是新增加的 比如 左括號 右括號 --><Buttonandroid:id="@+id/btn_log"android:layout_width="0dp"android:layout_height="@dimen/button_height"android:textSize="@dimen/button_font_size"android:layout_columnWeight="1"android:gravity="center"android:text="@string/log"android:textColor="@color/black"/><Buttonandroid:id="@+id/btn_ln"android:layout_width="0dp"android:layout_height="@dimen/button_height"android:textSize="@dimen/button_font_size"android:layout_columnWeight="1"android:gravity="center"android:text="ln"android:textColor="@color/black"/><Buttonandroid:id="@+id/btn_left_kh"android:layout_width="0dp"android:layout_height="@dimen/button_height"android:textSize="@dimen/button_font_size"android:layout_columnWeight="1"android:gravity="center"android:text="@string/left_kh"android:textColor="@color/black"/><Buttonandroid:id="@+id/btn_right_kh"android:layout_width="0dp"android:layout_height="@dimen/button_height"android:textSize="@dimen/button_font_size"android:layout_columnWeight="1"android:gravity="center"android:text="@string/right_kh"android:textColor="@color/black"/><!--下面是第二行--><Buttonandroid:id="@+id/btn_seven"android:layout_width="0dp"android:layout_height="@dimen/button_height"android:textSize="@dimen/button_font_size"android:layout_columnWeight="1"android:gravity="center"android:text="@string/seven"android:textColor="@color/black"/><Buttonandroid:id="@+id/btn_eight"android:layout_width="0dp"android:layout_height="@dimen/button_height"android:textSize="@dimen/button_font_size"android:layout_columnWeight="1"android:gravity="center"android:text="@string/eight"android:textColor="@color/black"/><Buttonandroid:id="@+id/btn_nine"android:layout_width="0dp"android:layout_height="@dimen/button_height"android:textSize="@dimen/button_font_size"android:layout_columnWeight="1"android:gravity="center"android:text="@string/nine"android:textColor="@color/black"/><Buttonandroid:id="@+id/btn_plus"android:layout_width="0dp"android:layout_height="@dimen/button_height"android:textSize="@dimen/button_font_size"android:layout_columnWeight="1"android:gravity="center"android:text="@string/plus"android:textColor="@color/black"/><Buttonandroid:id="@+id/btn_four"android:layout_width="0dp"android:layout_height="@dimen/button_height"android:textSize="@dimen/button_font_size"android:layout_columnWeight="1"android:gravity="center"android:text="@string/four"android:textColor="@color/black"/><Buttonandroid:id="@+id/btn_five"android:layout_width="0dp"android:layout_height="@dimen/button_height"android:textSize="@dimen/button_font_size"android:layout_columnWeight="1"android:gravity="center"android:text="@string/five"android:textColor="@color/black"/><Buttonandroid:id="@+id/btn_six"android:layout_width="0dp"android:layout_height="@dimen/button_height"android:textSize="@dimen/button_font_size"android:layout_columnWeight="1"android:gravity="center"android:text="@string/six"android:textColor="@color/black"/><Buttonandroid:id="@+id/btn_minus"android:layout_width="0dp"android:layout_height="@dimen/button_height"android:textSize="@dimen/button_font_size"android:layout_columnWeight="1"android:gravity="center"android:text="@string/minus"android:textColor="@color/black"/><Buttonandroid:id="@+id/btn_one"android:layout_width="0dp"android:layout_height="@dimen/button_height"android:textSize="@dimen/button_font_size"android:layout_columnWeight="1"android:gravity="center"android:text="@string/one"android:textColor="@color/black"/><Buttonandroid:id="@+id/btn_two"android:layout_width="0dp"android:layout_height="@dimen/button_height"android:textSize="@dimen/button_font_size"android:layout_columnWeight="1"android:gravity="center"android:text="@string/two"android:textColor="@color/black"/><Buttonandroid:id="@+id/btn_three"android:layout_width="0dp"android:layout_height="@dimen/button_height"android:textSize="@dimen/button_font_size"android:layout_columnWeight="1"android:gravity="center"android:text="@string/three"android:textColor="@color/black"/><!--這里顯示的根號的圖片--><Buttonandroid:id="@+id/btn_sqrt"android:layout_width="0dp"android:layout_height="@dimen/button_height"android:textSize="@dimen/button_font_size"android:layout_columnWeight="1"android:gravity="center"android:text="@string/sqrt"android:textColor="@color/black"/><Buttonandroid:id="@+id/btn_reciprocal"android:layout_width="0dp"android:layout_height="@dimen/button_height"android:textSize="@dimen/button_font_size"android:layout_columnWeight="1"android:gravity="center"android:text="@string/reciprocal"android:textColor="@color/black"/><Buttonandroid:id="@+id/btn_zero"android:layout_width="0dp"android:layout_height="@dimen/button_height"android:textSize="@dimen/button_font_size"android:layout_columnWeight="1"android:gravity="center"android:text="@string/zero"android:textColor="@color/black"/><Buttonandroid:id="@+id/btn_dot"android:layout_width="0dp"android:layout_height="@dimen/button_height"android:textSize="@dimen/button_font_size"android:layout_columnWeight="1"android:gravity="center"android:text="@string/dot"android:textColor="@color/black"/><Buttonandroid:id="@+id/btn_equal"android:layout_width="0dp"android:layout_height="@dimen/button_height"android:textSize="@dimen/button_font_size"android:layout_columnWeight="1"android:gravity="center"android:text="@string/equal"android:textColor="@color/black"/></GridLayout></LinearLayout></ScrollView></LinearLayout>

strings.xml里面的代碼:

<resources><string name="app_name">黃淮計算器</string><string name="action_settings">Settings</string><!-- Strings used for fragments for navigation --><string name="first_fragment_label">First Fragment</string><string name="second_fragment_label">Second Fragment</string><string name="next">Next</string><string name="previous">Previous</string><string name="hello_word">hello_word</string><string name="text_for_color">textForColor</string><string name="lorem_ipsum"></string><string name="findyou">FindYou</string><string name="this_is_findyou">This is FindYou</string><string name="this_is_activity_main_2">除了奮斗 別無選擇</string><!--計算器的定義--><string name="simple_calculator">黃淮計算器</string><string name="cancel">?</string><string name="divide">÷</string><string name="multiply">x</string><string name="clear">C</string><string name="seven">7</string><string name="eight">8</string><string name="nine">9</string><string name="plus">+</string><string name="four">4</string><string name="five">5</string><string name="six">6</string><string name="minus">-</string><string name="one">1</string><string name="two">2</string><string name="three">3</string><string name="reciprocal">1/x</string><string name="zero">0</string><string name="dot">.</string><string name="sqrt">√</string><string name="equal">=</string><string name="check_sex">請選擇你的性別</string><string name="PI">π</string><string name="e">e</string><string name="abs">|x|</string><string name="factorial">n!</string><string name="log">log</string><string name="left_kh">(</string><string name="right_kh">)</string></resources>

如果這對你有幫助的話,記得start一下哦,你的star對我很重要!!!

gitee地址:

FindYou/移動開發

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/76485.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/76485.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/76485.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

GMap.NET + WPF:構建高性能 ADS-B 航空器追蹤平臺

ADS-B 簡介 ADS - B&#xff08;Automatic Dependent Surveillance - Broadcast&#xff0c;廣播式自動相關監視&#xff09;是一種先進的航空監視技術。它依靠飛機上的機載設備&#xff0c;自動收集諸如飛機的位置、高度、速度、航向等關鍵數據&#xff0c;并周期性地以廣播的…

關于testng.xml無法找到類的問題

問題&#xff1a;testng.xml添加測試類的時候飄紅 解決辦法&#xff1a; 1.試圖通過自動生成testng.xml插件去解決&#xff0c;感覺也不是這個問題&#xff0c;沒有嘗試&#xff1b; 2.以為是創建包的方式不對&#xff0c;重新刪除后新建--還是找不到 想新建類的時候發現從m…

數據在內存中存儲(C語言)

文章目錄 前言一、整數在內存中的存儲1.1 計算機存儲數據的基本單位示例代碼 1.2 無符號整數的存儲1.3 有符號整數的存儲&#xff08;補碼&#xff09;示例代碼 二、大小端字節序和字節序判斷2.1 什么是大小端&#xff1f;示例代碼 2.2 為什么會有大小端&#xff1f;2.3 字節序…

Python爬蟲第2節-網頁基礎和爬蟲基本原理

目錄 一、網頁基礎 1.1 網頁的組成 1.2 網頁的結構 1.3 節點樹及節點間的關系 1.4 選擇器 二、爬蟲的基本原理 2.1 爬蟲概述 2.2 能抓怎樣的數據 2.3 JavaScript 渲染頁面 一、網頁基礎 使用瀏覽器訪問網站時&#xff0c;我們會看到各式各樣的頁面。你是否思考過&…

python-leetcode 64.在排序數組中查找元素的第一個和最后一個位置

題目&#xff1a; 給一個按照非遞減順序排列的整數數組nums,和一個目標值target,請找出給定目標值在數組中的開始位置和結束位置。 如果數組中不存在目標值target,返回[-1,-1] 方法一&#xff1a;二分查找 直觀的思路肯定是從前往后遍歷一遍。用兩個變量記錄第一次和最后一次…

分享一些新版GPT-4o使用方式!能多模態生圖!

目前GPT-4o的整體測評&#xff0c;真的很驚艷。 不知道又有多少人因為OpenAI的這次更新而失業&#xff0c;當然只要AI用得好&#xff0c;會有更多人因之而受益&#xff01;很多人表示不知道怎么用&#xff0c;對于門外漢來說&#xff0c;4o似乎有點高端。 今天就給大家介紹幾…

軟件工程面試題(二十四)

1、連接池的原理 j2ee 服務器啟動時會建立一定數量的池連接,并一直維持不少于此數量的池連接。當客戶端程序需要連接時,吃驅動程序會返回一個未使用的池連接并將其標記為忙。如果當前 沒有空閑連接,池驅動就建立一定新的 連接 2、用javascript編寫腳本小程序,實現點擊全選…

Android:Dialog的使用詳解

Android中Dialog的使用詳解 Dialog&#xff08;對話框&#xff09;是Android中常用的UI組件&#xff0c;用于臨時顯示重要信息或獲取用戶輸入。 1. 基本Dialog類型 1.1 AlertDialog&#xff08;警告對話框&#xff09; 最常用的對話框類型&#xff0c;可以設置標題、消息、…

arinc818 fpga單色圖像傳輸ip

arinc818協議支持的常用線速率如下圖 隨著圖像分辨率的提高&#xff0c;單lane的速率無法滿足特定需求&#xff0c;一種方式是通過多個LANE交叉的去傳輸圖像&#xff0c;另外一種是通過降低圖像的帶寬&#xff0c;即通過只傳單色圖像達到對應的效果 程序架構如下圖所示&#x…

透視投影(Perspective projection)與等距圓柱投影(Equirectangular projection)

一、透視投影 1.方法概述 Perspective projection&#xff08;透視投影&#xff09;是一種模擬人眼觀察三維空間物體時的視覺效果的投影方法。它通過模擬觀察者從一個特定視點觀察三維場景的方式來創建二維圖像。在透視投影中&#xff0c;遠處的物體看起來比近處的物體小&…

三.微服務架構中的精妙設計:服務注冊/服務發現-Eureka

一.使用注冊中心背景 1.1服務遠程調用問題 服務之間遠程調?時, 我們的URL是寫死的 String url "http://127.0.0.1:9090/product/" orderInfo.getProductId(); 缺點&#xff1a; 當更換機器, 或者新增機器時, 這個URL就需要跟著變更, 就需要去通知所有的相關服…

FPGA實現4K MIPI視頻解碼H265壓縮網絡推流輸出,基于IMX317+VCU架構,支持4K60幀,提供工程源碼和技術支持

目錄 1、前言工程概述免責聲明 2、相關方案推薦我已有的所有工程源碼總目錄----方便你快速找到自己喜歡的項目我這里已有的 MIPI 編解碼方案我這里已有的視頻圖像編解碼方案 3、詳細設計方案設計框圖FPGA開發板IMX317攝像頭MIPI D-PHYMIPI CSI-2 RX Subsystem圖像預處理Sensor …

Ollama+open-webui搭建私有本地大模型詳細教程

Ollamaopen-webui搭建私有本地大模型詳細教程 1. 什么是 Ollama&#xff1f; 1.1. Ollama 簡介 ? Ollama 是一個輕量級的 AI 模型運行時&#xff0c;專注于簡化 AI 模型的部署和使用。它支持多種預訓練模型&#xff08;如 Llama、Vicuna、Dolly 等&#xff09;&#xff0c;…

解決Centos7集成IDEA報git版本太低問題

Centos 7 服務器上默認安裝的 Git 是 1.8.3.1 版本的 與最新的IDEA已無法匹配&#xff0c;需要更新 首先&#xff0c;卸載老版本 sudo yum -y remove git sudo yum -y remove git-*添加 End Point 到 CentOS 7 倉庫 sudo yum -y install https://packages.endpointdev.com/r…

Qt常用宏定義判斷大全

Qt 提供了一系列預定義宏用于判斷 Qt 版本、操作系統平臺、編譯器特性等。這些宏在跨平臺開發中非常有用。 1. Qt 版本判斷宏 // 檢查Qt版本 #if QT_VERSION > QT_VERSION_CHECK(5, 15, 0)// Qt 5.15.0及以上版本特有代碼 #endif// 常用版本判斷 #if QT_VERSION > QT_V…

實戰 | 餐廳點餐小程序技術解析:SpringBoot + UniApp 高效開發指南

&#x1f5a5;? 一、系統架構概覽 1.1 技術選型 為了確保開發效率和系統穩定性&#xff0c;我們采用以下技術棧&#xff1a; 模塊技術選型后臺服務SpringBoot MyBatis-Plus MySQL用戶端&#xff08;點餐小程序&#xff09;UniApp&#xff08;Vue 語法&#xff09;師傅端&…

實現在Unity3D中仿真汽車,而且還能使用ros2控制

文章目錄 前言&#xff08;Introduction&#xff09;搭建開發環境&#xff08;Setup Development Environment&#xff09;在window中安裝Unity&#xff08;Install Unity in window&#xff09;創建Docker容器&#xff0c;并安裝相關軟件&#xff08;Create Docker containers…

華為配置篇-BGP實驗

BGP 一、簡述二、常用命令總結三、實驗 一、簡述 IBGP 水平分割&#xff1a;從一個 IBGP 對等體學到的路由&#xff0c;不會再通告給其他的 IBGP 對等體。在一個 AS 內部&#xff0c;路由器之間通過 IBGP 交換路由信息。如果沒有水平分割機制&#xff0c;當多個路由器之間形成…

Python視頻標簽工具詳解:基于wxPython和FFmpeg的實現

在當今數字媒體時代&#xff0c;視頻內容的管理和標記變得越來越重要。無論是研究人員需要對實驗視頻進行時間點標記&#xff0c;教育工作者需要對教學視頻添加注釋&#xff0c;還是個人用戶希望對家庭視頻進行分類整理&#xff0c;一個高效的視頻標簽工具都是不可或缺的。本文…

國產三維CAD「皇冠CAD」在汽車零部件領域建模教程:剎車片

本教程深度融合三維皇冠CAD&#xff08;CrownCAD&#xff09;的MBD&#xff08;Model-Based Definition&#xff09;設計理念&#xff0c;通過參數化建模、智能約束管理、動態裝配驗證等功能&#xff0c;實現數據驅動設計&#xff0c;精準解決了汽車制動系統中精密制動組件的設…