<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
本次設計的是一個有33個按鈕的科學計算器。可以進行加,減,乘,除,開根號,階乘,次方,百分號,對數,三角函數的計算。
通過點選按鈕可以得到一個算術表示式,並且它是一個字串型別,然後需要做的就是把這個字串轉化為計算機可計算的形式。這裡就需要用到中綴表示式轉化為字尾表示式。轉化完之後通過棧來一步步的進行輸出和計算,最後輸出結果。
設計效果如圖所示:
由圖片可知,總共設計了兩個文字方塊和33個按鈕(這裡的佈局是我直接用setBounds()方法設計的。因為如果用佈局管理器的話要達到自己想要的效果不太方便)。
在設計時要注意的是:
1.不能把按鈕和文字方塊直接加入JFrame中,因為如果JFrame.setLayout(null)的話,面板上就會出問題,什麼都看不到或者其他情況。因此建議建立一個JPanel,把JPanel的setLayout()設定為空。把按鈕和文字方塊加入到JPanel中,再把JPanel加入到JFrame中。就不會出問題了。JFrame的佈局管理器預設為流式佈局,位置是中心區域。
2.設計完長度後,寬度一般要再加15個畫素點,高度要再加35個畫素點.要不然會有一部分按鈕看不到。如我本意要設計的面板寬為600,高為400,則實際上是
jFrame.setSize(614, 437);
下面就是我設計的介面的程式碼:
private JFrame jFrame = new JFrame("計算器"); //設定字型,是否加粗,大小 private FontUIResource f = new FontUIResource("隸書", 1, 20); private FontUIResource f1 = new FontUIResource("楷書", 0, 35); private JPanel jPanel = new JPanel(); private int buttonx = 100; private int buttony = 50; private int yy = 50; //兩個文字方塊 private JTextField jTextField1 = new JTextField("0", 30); private JTextField jTextField2 = new JTextField("輸入要求在main()中", 30); private String str = ""; private String temp = ""; private int indexYN = 0; private String[] strings = { "(", ")", "1/x", "x^2", "x^3", "x^y", "x!", "√", "e", "ln", "log", "%", "sin", "cos", "tan", "π", "+", "=", "7", "8", "9", "0", "-", "4", "5", "6", ".", "*", "1", "2", "3", "c", "÷" }; //33個按鈕 private JButton[] buttons = new JButton[33]; public void loAsi(){ int tep = 0; for (int i = 0; i < 3; i++) { for (int j = 0; j < 6; j++) { buttons[tep] = new JButton(strings[tep]); buttons[tep].setFont(f); buttons[tep++].setFocusable(false); } } for (int i = 0; i < 3; i++) { for (int j = 0; j < 5; j++) { buttons[tep] = new JButton(strings[tep]); buttons[tep].setFont(f); buttons[tep++].setFocusable(false); } } int lo = 0; for (int i = 0; i < 2; i++) { for (int j = 0; j < 6; j++) { buttons[lo++].setBounds(buttonx * j, yy * (2 + i), buttonx, buttony); } } for (int i = 0; i < 5; i++) { buttons[lo++].setBounds(buttonx * i, yy * 4, buttonx, buttony); } buttons[lo++].setBounds(buttonx * 5, yy * 4, buttonx, buttony * 4); for (int i = 0; i < 3; i++) { for (int j = 0; j < 5; j++) { buttons[lo++].setBounds(buttonx * j, yy * (5 + i), buttonx, buttony); } } jTextField1.setBounds(0, yy, 600, yy);//設定位置 jTextField1.setFont(f1);設定字型 jTextField1.setHorizontalAlignment(JLabel.RIGHT);//文字靠右 jTextField1.setEditable(false);//不可修改 jTextField1.setBackground(Color.WHITE);//顏色為白色 jTextField2.setBounds(0, 0, 600, yy); jTextField2.setFont(f1); jTextField2.setHorizontalAlignment(JLabel.RIGHT); jTextField2.setEditable(false); jTextField2.setBackground(Color.WHITE); } public void initButton(){//把按鈕新增到jPanel中 this.loAsi(); jPanel.add(jTextField1); jPanel.add(jTextField2); for (int i = 0; i < buttons.length; i++) { jPanel.add(buttons[i]); } jPanel.setLayout(null);//佈局管理器為空,自定義設計 } public void init(){ this.initButton(); this.buttonLister(); jFrame.add(jPanel);//把jPanel新增到jFrame中 jFrame.setSize(614, 437);//jFrame的長寬 jFrame.setResizable(false);//大小不可修改 jFrame.setLocationRelativeTo(null);//位置為顯示器的正中間 //視窗監聽器,點右上角的關閉就關閉視窗 //可以不寫,應為JFrame預設的就可以關閉,不需要寫事件監聽器。如果是Frame的話需要寫。 jFrame.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { System.exit(0); } }); jFrame.setVisible(true);//設定面板可見 }
我總共設計了12種運運算元:(+, -, * , /, ^, !, g, l, o, s, c, t)分別是加,減,乘,除,次方,階乘,開根號,,對數ln, 對數log2, sin, cos, tan
e是Math.E, p是Math.PI, %是直接乘以0.001
把中綴表示式轉換為字尾表示式。例如:
中綴表示式:1+2*3+(l2+3)/2
字尾表示式為:123*+23+2/+
字尾表示式的運算步驟是:
1.16+23+2/+
2.723+2/+
3.752/+
4.7 2.5+
5.9.5
程式碼如下:
private List<String> zhongZhui(String str) {//把輸入的字串轉換成中綴表示式。存入list中 int index = 0; List<String> list = new ArrayList<>(); do{ char ch = str.charAt(index); if("+-*/^!logsct()".indexOf(str.charAt(index)) >= 0){ //是操作符,直接新增至list中 index ++; list.add(ch+""); }else if (str.charAt(index) == 'e' || str.charAt(index) == 'p'){ index ++; list.add(ch+""); } else if("0123456789".indexOf(str.charAt(index)) >= 0){ //是數位,判斷多位數的情況 String str1 = ""; while (index < str.length() && "0123456789.".indexOf(str.charAt(index)) >= 0){ str1 += str.charAt(index); index ++; } list.add(str1); } }while (index < str.length()); return list; } public List<String> houZhui(List<String> list){//中綴表示式轉換稱字尾表示式 Stack<String> fuZhan = new Stack<>(); List<String> list2 = new ArrayList<>(); if (!list.isEmpty()) { for (int i = 0; i < list.size(); i++) { if (isNumber(list.get(i))){ list2.add(list.get(i)); } else if (list.get(i).charAt(0) == '('){ fuZhan.push(list.get(i)); } else if (isOperator(list.get(i)) && list.get(i).charAt(0) != '('){ if (fuZhan.isEmpty()){ fuZhan.push(list.get(i)); } else {//符棧不為空 if (list.get(i).charAt(0) != ')'){ if (adv(fuZhan.peek()) <= adv(list.get(i))){ //入棧 fuZhan.push(list.get(i)); } else {//出棧 while (!fuZhan.isEmpty() && !"(".equals(fuZhan.peek())){ if(adv(list.get(i)) <= adv(fuZhan.peek())){ list2.add(fuZhan.pop()); } } if (fuZhan.isEmpty() || fuZhan.peek().charAt(0) == '('){ fuZhan.push(list.get(i)); } } } else if (list.get(i).charAt(0) == ')'){ while (fuZhan.peek().charAt(0) != '('){ list2.add(fuZhan.pop()); } fuZhan.pop(); } } } } while (!fuZhan.isEmpty()){ list2.add(fuZhan.pop()); } } else { jTextField1.setText(""); } return list2; } public static boolean isOperator(String op){//判斷是否為操作符 if ("0123456789.ep".indexOf(op.charAt(0)) == -1) { return true; } else { return false; } } public static boolean isNumber(String num){//判斷是否為運算元 if ("0123456789ep".indexOf(num.charAt(0)) >= 0) { return true; } else { return false; } } public static int adv(String f){//判斷操作符的優先順序 int result = 0; switch(f) { case "+": result = 1; break; case "-": result = 1; break; case "*": result = 2; break; case "/": result = 2; break; case "^": result = 3; break; case "!": result = 4; break; case "g": result = 4; break; case "l": result = 4; break; case "o": result = 4; break; case "s": result = 4; break; case "c": result = 4; break; case "t": result = 4; break; } return result; }
下面是一些我能想到的一些輸入錯誤和運算錯誤:
//當只有一位字元時,只能是“0123456789ep”中的一個
//1.第一個字元只能為"losctg(0123456789ep"中的一個
//2.“±/”後面只能是"0123456789losctg(ep"中的一個
//3.".“後面只能是“0123456789”中的一個
//4.”!"後面只能是“±/^)”中的一個
//5."losctg"後面只能是“0123456789(ep”中的一個
//6."0"的判斷操作
//1.當0的上一個字元不為"0123456789."時,後一位只能是“±/.!^)”中的一個
//2.如果0的上一位為“.”,則後一位只能是“0123456789±/.^)”中的一個
//3.如果0到上一個運運算元之間沒有“.”的話,整數位第一個只能是“123456789”,
// 且後一位只能是“0123456789±/.!^)”中的一個。
//4.如果0到上一個運運算元之間有一個“.”的話,則後一位只能是“0123456789±/.^)”中的一個
//7."123456789"後面只能是“0123456789±/.!^)”中的一個
//8."(“後面只能是“0123456789locstg()ep”中的一個
//9.”)"後面只能是“±/!^)”中的一個
//10.最後一位字元只能是“0123456789!)ep”中的一個
//12.不能有多個“.”
//13."ep"後面只能是“±*/^)”中的一個
除數不能為0
階乘必須為自然數
ln的x必須大於0
log的x必須大於0
tan的x不能為±(π/2 + kπ)
括號是否匹配
程式碼如下:
public void estimate(){//判斷輸入是否錯誤 int i = 0; if (str.length() == 0){ } if (str.length() == 1){ //當只有一位字元時,只能是「0123456789ep」中的一個 if ("0123456789ep".indexOf(str.charAt(0)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } } if (str.length() > 1){ for (i = 0; i < str.length() - 1; i++) { //1.第一個字元只能為"losctg(0123456789ep"中的一個 if ("losctg(0123456789ep".indexOf(str.charAt(0)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } //2.「+-*/」後面只能是"0123456789losctg(ep"中的一個 if ("+-*/".indexOf(str.charAt(i)) >= 0 && "0123456789losctg(ep".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } //3."."後面只能是「0123456789」中的一個 if (str.charAt(i) == '.' && "0123456789".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } //4."!"後面只能是「+-*/^)」中的一個 if (str.charAt(i) == '!' && "+-*/^)".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } //5."losctg"後面只能是「0123456789(ep」中的一個 if ("losctg".indexOf(str.charAt(i)) >= 0 && "0123456789(ep".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } //6."0"的判斷操作 if (str.charAt(0) == '0' && str.charAt(1) == '0'){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } if (i >= 1 && str.charAt(i) == '0'){ //&& str.charAt(0) == '0' && str.charAt(1) == '0' int m = i; int n = i; int is = 0; //1.當0的上一個字元不為"0123456789."時,後一位只能是「+-*/.!^)」中的一個 if ("0123456789.".indexOf(str.charAt(m - 1)) == -1 && "+-*/.!^)".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } //2.如果0的上一位為「.」,則後一位只能是「0123456789+-*/.^)」中的一個 if (str.charAt(m - 1) == '.' && "0123456789+-*/.^)".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } n -= 1; while (n > 0){ if ("(+-*/^glosct".indexOf(str.charAt(n)) >= 0){ break; } if (str.charAt(n) == '.'){ is++; } n--; } //3.如果0到上一個運運算元之間沒有「.」的話,整數位第一個只能是「123456789」, // 且後一位只能是「0123456789+-*/.!^)」中的一個。 if ((is == 0 && str.charAt(n) == '0') || "0123456789+-*/.!^)".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } //4.如果0到上一個運運算元之間有一個「.」的話,則後一位只能是「0123456789+-*/.^)」中的一個 if (is == 1 && "0123456789+-*/.^)".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } if (is > 1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } } //7."123456789"後面只能是「0123456789+-*/.!^)」中的一個 if ("123456789".indexOf(str.charAt(i)) >= 0 && "0123456789+-*/.!^)".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } //8."("後面只能是「0123456789locstg()ep」中的一個 if (str.charAt(i) == '(' && "0123456789locstg()ep".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } //9.")"後面只能是「+-*/!^)」中的一個 if (str.charAt(i) == ')' && "+-*/!^)".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } //10.最後一位字元只能是「0123456789!)ep」中的一個 if ("0123456789!)ep".indexOf(str.charAt(str.length() - 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } //12.不能有多個「.」 if (i > 2 && str.charAt(i) == '.'){ int n = i - 1; int is = 0; while (n > 0){ if ("(+-*/^glosct".indexOf(str.charAt(n)) >= 0){ break; } if (str.charAt(n) == '.'){ is++; } n--; } if (is > 0){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } } //13."ep"後面只能是「+-*/^)」中的一個 if ("ep".indexOf(str.charAt(i)) >= 0 && "+-*/^)".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } } } }
程式碼如下:
public double math(List<String> list2) {//通過字尾表示式進行計算 Stack<String> stack = new Stack<String>(); for (int i = 0; i < list2.size(); i++) { if (isNumber(list2.get(i))) { if (list2.get(i).charAt(0) == 'e'){ stack.push(String.valueOf(Math.E)); } else if (list2.get(i).charAt(0) == 'p'){ stack.push(String.valueOf(Math.PI)); } else { stack.push(list2.get(i)); } } else if (isOperator(list2.get(i))){ double res = 0; if (list2.get(i).equals("+")) { double num2 = Double.parseDouble(stack.pop()); double num1 = Double.parseDouble(stack.pop()); res = num1 + num2; } else if (list2.get(i).equals("-")) { double num2 = Double.parseDouble(stack.pop()); double num1 = Double.parseDouble(stack.pop()); res = num1 - num2; } else if (list2.get(i).equals("*")) { double num2 = Double.parseDouble(stack.pop()); double num1 = Double.parseDouble(stack.pop()); res = num1 * num2; } else if (list2.get(i).equals("/")) { double num2 = Double.parseDouble(stack.pop()); double num1 = Double.parseDouble(stack.pop()); if (num2 != 0){ res = num1 / num2; } else { jTextField1.setText("除數不能為0"); indexYN = 1; } } else if (list2.get(i).equals("^")) { double num2 = Double.parseDouble(stack.pop()); double num1 = Double.parseDouble(stack.pop()); res = Math.pow(num1, num2); } else if (list2.get(i).equals("!")) { double num1 = Double.parseDouble(stack.pop()); if (num1 == 0 || num1 == 1){ res = 1; } else if (num1 == (int)num1 && num1 > 1){ int d = 1; for (int j = (int)num1; j >0; j--) { d *= j; } res = d; } else { jTextField1.setText("階乘必須為自然數"); indexYN = 1; } } else if (list2.get(i).equals("g")) { double num1 = Double.parseDouble(stack.pop()); res = Math.sqrt(num1); } else if (list2.get(i).equals("l")) { double num1 = Double.parseDouble(stack.pop()); if (num1 > 0){ res = Math.log(num1); } else { jTextField1.setText("ln的x必須大於0"); indexYN = 1; } } else if (list2.get(i).equals("o")) { double num1 = Double.parseDouble(stack.pop()); if (num1 > 0){ res = Math.log(num1) / Math.log(2); } else { jTextField1.setText("log的x必須大於0"); indexYN = 1; } } else if (list2.get(i).equals("s")) { double num1 = Double.parseDouble(stack.pop()); res = Math.sin(num1); } else if (list2.get(i).equals("c")) { double num1 = Double.parseDouble(stack.pop()); res = Math.cos(num1); } else if (list2.get(i).equals("t")) { double num1 = Double.parseDouble(stack.pop()); if (Math.cos(num1) != 0){ res = Math.tan(num1); } else { jTextField1.setText("tan的x不能為+-(π/2 + kπ)"); indexYN = 1; } } stack.push("" + res); } } if (indexYN == 0){ if (!stack.isEmpty()){ return Double.parseDouble(stack.pop()); } else { return 0; } } else { return -999999; } } public void zhanDui(){//進行計算,並且判斷括號是否匹配 String khao = ""; int leftkh = 0; int rightkh = 0; int m = 0; //判斷括號是否成對 for (int i = 0; i < str.length(); i++) { if (str.charAt(i) == '('){ khao += '('; leftkh++; } if (str.charAt(i) == ')'){ khao += ')'; rightkh++; } } if (leftkh != rightkh){ jTextField1.setText("輸入錯誤!括號不匹配"); indexYN = 1; } if ((leftkh == 0 && rightkh == 0) || ((leftkh == rightkh && leftkh > 0) && khao.charAt(0) == '(' && khao.charAt(khao.length() - 1) == ')')){ if (indexYN == 0){ List<String> list1 = zhongZhui(str); //System.out.println(list1); List<String> list2 = houZhui(list1); //System.out.println(list2); if (indexYN == 0){ if (math(list2) == -999999){ jTextField1.setText(jTextField1.getText()); } else { jTextField1.setText(String.valueOf(math(list2))); jTextField2.setText(String.valueOf(math(list2))); jTextField2.setText(String.valueOf(math(list2))); } } } } else { jTextField1.setText("輸入錯誤!括號不匹配"); indexYN = 1; } }
因為設定了33個按鈕,所以每個按鈕都要設計事件監聽器,我設定的目的是把點中的按鈕的值寫入到文字方塊中輸出,並且把它代表的數值或者操作符存放到字串中,以便於進行中綴轉字尾和運算。
程式碼如下:
public void buttonLister(){//事件監聽器 int tep = 0; buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "("); str += "("; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + ")"); str += ")"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "1/"); str += "1/"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "^2"); str += "^2"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "^3"); str += "^3"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "^"); str += "^"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "!"); str += "!"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "√"); str += "g"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "e"); str += "e"; //str += "2.7182818284590452354"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "ln"); str += "l"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "log"); str += "o"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "%"); str += "*0.01"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "sin"); str += "s"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "cos"); str += "c"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "tan"); str += "t"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "π"); str += "p"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "+"); str += "+"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (str != ""){ estimate(); zhanDui(); } else { str = ""; } } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "7"); str += "7"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "8"); str += "8"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "9"); str += "9"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "0"); str += "0"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "-"); str += "-"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "4"); str += "4"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "5"); str += "5"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "6"); str += "6"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "."); str += "."; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "*"); str += "*"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "1"); str += "1"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "2"); str += "2"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "3"); str += "3"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(""); str = ""; indexYN = 0; } }); buttons[tep].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "÷"); str += "/"; } }); }
直接拷貝到Java中就可以用:
一個類走完程式。
main函數中還可以設定面板風格。有
三種風格可以自定義選擇,我個人覺得Niumbus風格比較好看。選擇哪一個就釋放哪一個,把另外兩個註釋掉就可以了。
package com.lmdxyt; import javax.swing.*; import javax.swing.plaf.FontUIResource; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.ArrayList; import java.util.List; import java.util.Stack; public class JSQ { private JFrame jFrame = new JFrame("計算器"); private FontUIResource f = new FontUIResource("隸書", 1, 20); private FontUIResource f1 = new FontUIResource("楷書", 0, 35); private JPanel jPanel = new JPanel(); private int buttonx = 100; private int buttony = 50; private int yy = 50; private JTextField jTextField1 = new JTextField("0", 30); private JTextField jTextField2 = new JTextField("輸入要求在main()中", 30); private String str = ""; private String temp = ""; private int indexYN = 0; private String[] strings = { "(", ")", "1/x", "x^2", "x^3", "x^y", "x!", "√", "e", "ln", "log", "%", "sin", "cos", "tan", "π", "+", "=", "7", "8", "9", "0", "-", "4", "5", "6", ".", "*", "1", "2", "3", "c", "÷" }; private JButton[] buttons = new JButton[33]; public void loAsi(){ int tep = 0; for (int i = 0; i < 3; i++) { for (int j = 0; j < 6; j++) { buttons[tep] = new JButton(strings[tep]); buttons[tep].setFont(f); buttons[tep++].setFocusable(false); } } for (int i = 0; i < 3; i++) { for (int j = 0; j < 5; j++) { buttons[tep] = new JButton(strings[tep]); buttons[tep].setFont(f); buttons[tep++].setFocusable(false); } } int lo = 0; for (int i = 0; i < 2; i++) { for (int j = 0; j < 6; j++) { buttons[lo++].setBounds(buttonx * j, yy * (2 + i), buttonx, buttony); } } for (int i = 0; i < 5; i++) { buttons[lo++].setBounds(buttonx * i, yy * 4, buttonx, buttony); } buttons[lo++].setBounds(buttonx * 5, yy * 4, buttonx, buttony * 4); for (int i = 0; i < 3; i++) { for (int j = 0; j < 5; j++) { buttons[lo++].setBounds(buttonx * j, yy * (5 + i), buttonx, buttony); } } jTextField1.setBounds(0, yy, 600, yy); jTextField1.setFont(f1); jTextField1.setHorizontalAlignment(JLabel.RIGHT); jTextField1.setEditable(false); jTextField1.setBackground(Color.WHITE); jTextField2.setBounds(0, 0, 600, yy); jTextField2.setFont(f1); jTextField2.setHorizontalAlignment(JLabel.RIGHT); jTextField2.setEditable(false); jTextField2.setBackground(Color.WHITE); } public void initButton(){//把按鈕新增到jPanel中 this.loAsi(); jPanel.add(jTextField1); jPanel.add(jTextField2); for (int i = 0; i < buttons.length; i++) { jPanel.add(buttons[i]); } jPanel.setLayout(null); } private List<String> zhongZhui(String str) {//把輸入的字串轉換成中綴表示式。存入list中 int index = 0; List<String> list = new ArrayList<>(); do{ char ch = str.charAt(index); if("+-*/^!logsct()".indexOf(str.charAt(index)) >= 0){ //是操作符,直接新增至list中 index ++; list.add(ch+""); }else if (str.charAt(index) == 'e' || str.charAt(index) == 'p'){ index ++; list.add(ch+""); } else if("0123456789".indexOf(str.charAt(index)) >= 0){ //是數位,判斷多位數的情況 String str1 = ""; while (index < str.length() && "0123456789.".indexOf(str.charAt(index)) >= 0){ str1 += str.charAt(index); index ++; } list.add(str1); } }while (index < str.length()); return list; } public List<String> houZhui(List<String> list){//中綴表示式轉換稱字尾表示式 Stack<String> fuZhan = new Stack<>(); List<String> list2 = new ArrayList<>(); if (!list.isEmpty()) { for (int i = 0; i < list.size(); i++) { if (isNumber(list.get(i))){ list2.add(list.get(i)); } else if (list.get(i).charAt(0) == '('){ fuZhan.push(list.get(i)); } else if (isOperator(list.get(i)) && list.get(i).charAt(0) != '('){ if (fuZhan.isEmpty()){ fuZhan.push(list.get(i)); } else {//符棧不為空 if (list.get(i).charAt(0) != ')'){ if (adv(fuZhan.peek()) <= adv(list.get(i))){ //入棧 fuZhan.push(list.get(i)); } else {//出棧 while (!fuZhan.isEmpty() && !"(".equals(fuZhan.peek())){ if(adv(list.get(i)) <= adv(fuZhan.peek())){ list2.add(fuZhan.pop()); } } if (fuZhan.isEmpty() || fuZhan.peek().charAt(0) == '('){ fuZhan.push(list.get(i)); } } } else if (list.get(i).charAt(0) == ')'){ while (fuZhan.peek().charAt(0) != '('){ list2.add(fuZhan.pop()); } fuZhan.pop(); } } } } while (!fuZhan.isEmpty()){ list2.add(fuZhan.pop()); } } else { jTextField1.setText(""); } return list2; } public static boolean isOperator(String op){//判斷是否為操作符 if ("0123456789.ep".indexOf(op.charAt(0)) == -1) { return true; } else { return false; } } public static boolean isNumber(String num){//判斷是否為運算元 if ("0123456789ep".indexOf(num.charAt(0)) >= 0) { return true; } else { return false; } } public static int adv(String f){//判斷操作符的優先順序 int result = 0; switch(f) { case "+": result = 1; break; case "-": result = 1; break; case "*": result = 2; break; case "/": result = 2; break; case "^": result = 3; break; case "!": result = 4; break; case "g": result = 4; break; case "l": result = 4; break; case "o": result = 4; break; case "s": result = 4; break; case "c": result = 4; break; case "t": result = 4; break; } return result; } public void buttonLister(){//事件監聽器 int tep = 0; buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "("); str += "("; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + ")"); str += ")"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "1/"); str += "1/"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "^2"); str += "^2"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "^3"); str += "^3"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "^"); str += "^"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "!"); str += "!"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "√"); str += "g"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "e"); str += "e"; //str += "2.7182818284590452354"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "ln"); str += "l"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "log"); str += "o"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "%"); str += "*0.01"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "sin"); str += "s"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "cos"); str += "c"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "tan"); str += "t"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "π"); str += "p"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "+"); str += "+"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (str != ""){ estimate(); zhanDui(); } else { str = ""; } } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "7"); str += "7"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "8"); str += "8"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "9"); str += "9"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "0"); str += "0"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "-"); str += "-"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "4"); str += "4"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "5"); str += "5"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "6"); str += "6"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "."); str += "."; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "*"); str += "*"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "1"); str += "1"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "2"); str += "2"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "3"); str += "3"; } }); buttons[tep++].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(""); str = ""; indexYN = 0; } }); buttons[tep].addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jTextField1.setText(jTextField1.getText() + "÷"); str += "/"; } }); } public void init(){ this.initButton(); this.buttonLister(); jFrame.add(jPanel); jFrame.setSize(614, 437); jFrame.setResizable(false); jFrame.setLocationRelativeTo(null); jFrame.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { System.exit(0); } }); jFrame.setVisible(true); } public void estimate(){//判斷輸入是否錯誤 int i = 0; if (str.length() == 0){ } if (str.length() == 1){ //當只有一位字元時,只能是「0123456789ep」中的一個 if ("0123456789ep".indexOf(str.charAt(0)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } } if (str.length() > 1){ for (i = 0; i < str.length() - 1; i++) { //1.第一個字元只能為"losctg(0123456789ep"中的一個 if ("losctg(0123456789ep".indexOf(str.charAt(0)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } //2.「+-*/」後面只能是"0123456789losctg(ep"中的一個 if ("+-*/".indexOf(str.charAt(i)) >= 0 && "0123456789losctg(ep".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } //3."."後面只能是「0123456789」中的一個 if (str.charAt(i) == '.' && "0123456789".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } //4."!"後面只能是「+-*/^)」中的一個 if (str.charAt(i) == '!' && "+-*/^)".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } //5."losctg"後面只能是「0123456789(ep」中的一個 if ("losctg".indexOf(str.charAt(i)) >= 0 && "0123456789(ep".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } //6."0"的判斷操作 if (str.charAt(0) == '0' && str.charAt(1) == '0'){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } if (i >= 1 && str.charAt(i) == '0'){ //&& str.charAt(0) == '0' && str.charAt(1) == '0' int m = i; int n = i; int is = 0; //1.當0的上一個字元不為"0123456789."時,後一位只能是「+-*/.!^)」中的一個 if ("0123456789.".indexOf(str.charAt(m - 1)) == -1 && "+-*/.!^)".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } //2.如果0的上一位為「.」,則後一位只能是「0123456789+-*/.^)」中的一個 if (str.charAt(m - 1) == '.' && "0123456789+-*/.^)".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } n -= 1; while (n > 0){ if ("(+-*/^glosct".indexOf(str.charAt(n)) >= 0){ break; } if (str.charAt(n) == '.'){ is++; } n--; } //3.如果0到上一個運運算元之間沒有「.」的話,整數位第一個只能是「123456789」, // 且後一位只能是「0123456789+-*/.!^)」中的一個。 if ((is == 0 && str.charAt(n) == '0') || "0123456789+-*/.!^)".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } //4.如果0到上一個運運算元之間有一個「.」的話,則後一位只能是「0123456789+-*/.^)」中的一個 if (is == 1 && "0123456789+-*/.^)".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } if (is > 1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } } //7."123456789"後面只能是「0123456789+-*/.!^)」中的一個 if ("123456789".indexOf(str.charAt(i)) >= 0 && "0123456789+-*/.!^)".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } //8."("後面只能是「0123456789locstg()ep」中的一個 if (str.charAt(i) == '(' && "0123456789locstg()ep".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } //9.")"後面只能是「+-*/!^)」中的一個 if (str.charAt(i) == ')' && "+-*/!^)".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } //10.最後一位字元只能是「0123456789!)ep」中的一個 if ("0123456789!)ep".indexOf(str.charAt(str.length() - 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } //12.不能有多個「.」 if (i > 2 && str.charAt(i) == '.'){ int n = i - 1; int is = 0; while (n > 0){ if ("(+-*/^glosct".indexOf(str.charAt(n)) >= 0){ break; } if (str.charAt(n) == '.'){ is++; } n--; } if (is > 0){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } } //13."ep"後面只能是「+-*/^)」中的一個 if ("ep".indexOf(str.charAt(i)) >= 0 && "+-*/^)".indexOf(str.charAt(i + 1)) == -1){ jTextField1.setText("輸入錯誤!"); indexYN = 1; } } } } public double math(List<String> list2) {//通過字尾表示式進行計算 Stack<String> stack = new Stack<String>(); for (int i = 0; i < list2.size(); i++) { if (isNumber(list2.get(i))) { if (list2.get(i).charAt(0) == 'e'){ stack.push(String.valueOf(Math.E)); } else if (list2.get(i).charAt(0) == 'p'){ stack.push(String.valueOf(Math.PI)); } else { stack.push(list2.get(i)); } } else if (isOperator(list2.get(i))){ double res = 0; if (list2.get(i).equals("+")) { double num2 = Double.parseDouble(stack.pop()); double num1 = Double.parseDouble(stack.pop()); res = num1 + num2; } else if (list2.get(i).equals("-")) { double num2 = Double.parseDouble(stack.pop()); double num1 = Double.parseDouble(stack.pop()); res = num1 - num2; } else if (list2.get(i).equals("*")) { double num2 = Double.parseDouble(stack.pop()); double num1 = Double.parseDouble(stack.pop()); res = num1 * num2; } else if (list2.get(i).equals("/")) { double num2 = Double.parseDouble(stack.pop()); double num1 = Double.parseDouble(stack.pop()); if (num2 != 0){ res = num1 / num2; } else { jTextField1.setText("除數不能為0"); indexYN = 1; } } else if (list2.get(i).equals("^")) { double num2 = Double.parseDouble(stack.pop()); double num1 = Double.parseDouble(stack.pop()); res = Math.pow(num1, num2); } else if (list2.get(i).equals("!")) { double num1 = Double.parseDouble(stack.pop()); if (num1 == 0 || num1 == 1){ res = 1; } else if (num1 == (int)num1 && num1 > 1){ int d = 1; for (int j = (int)num1; j >0; j--) { d *= j; } res = d; } else { jTextField1.setText("階乘必須為自然數"); indexYN = 1; } } else if (list2.get(i).equals("g")) { double num1 = Double.parseDouble(stack.pop()); res = Math.sqrt(num1); } else if (list2.get(i).equals("l")) { double num1 = Double.parseDouble(stack.pop()); if (num1 > 0){ res = Math.log(num1); } else { jTextField1.setText("ln的x必須大於0"); indexYN = 1; } } else if (list2.get(i).equals("o")) { double num1 = Double.parseDouble(stack.pop()); if (num1 > 0){ res = Math.log(num1) / Math.log(2); } else { jTextField1.setText("log的x必須大於0"); indexYN = 1; } } else if (list2.get(i).equals("s")) { double num1 = Double.parseDouble(stack.pop()); res = Math.sin(num1); } else if (list2.get(i).equals("c")) { double num1 = Double.parseDouble(stack.pop()); res = Math.cos(num1); } else if (list2.get(i).equals("t")) { double num1 = Double.parseDouble(stack.pop()); if (Math.cos(num1) != 0){ res = Math.tan(num1); } else { jTextField1.setText("tan的x不能為+-(π/2 + kπ)"); indexYN = 1; } } stack.push("" + res); } } if (indexYN == 0){ if (!stack.isEmpty()){ return Double.parseDouble(stack.pop()); } else { return 0; } } else { return -999999; } } public void zhanDui(){//進行計算,並且判斷括號是否匹配 String khao = ""; int leftkh = 0; int rightkh = 0; int m = 0; //判斷括號是否成對 for (int i = 0; i < str.length(); i++) { if (str.charAt(i) == '('){ khao += '('; leftkh++; } if (str.charAt(i) == ')'){ khao += ')'; rightkh++; } } if (leftkh != rightkh){ jTextField1.setText("輸入錯誤!括號不匹配"); indexYN = 1; } if ((leftkh == 0 && rightkh == 0) || ((leftkh == rightkh && leftkh > 0) && khao.charAt(0) == '(' && khao.charAt(khao.length() - 1) == ')')){ if (indexYN == 0){ List<String> list1 = zhongZhui(str); //System.out.println(list1); List<String> list2 = houZhui(list1); //System.out.println(list2); if (indexYN == 0){ if (math(list2) == -999999){ jTextField1.setText(jTextField1.getText()); } else { jTextField1.setText(String.valueOf(math(list2))); jTextField2.setText(String.valueOf(math(list2))); jTextField2.setText(String.valueOf(math(list2))); } } } } else { jTextField1.setText("輸入錯誤!括號不匹配"); indexYN = 1; } } public static void main(String[] args) { /* * 1.在輸入過程中每兩個數值之間必須有運運算元,否則報錯. * 例如:錯誤:2ln4(5+8), 2sin2 等 * 正確:2*ln4*(5+8), 2*sin2 * 2.不支援負數,要想得到負數,只能0-x * 例如:錯誤:-2+3*(-2*6) * 正確:0-2+3*((0-2)+6) * */ new JSQ().init(); //Niumbus風格 try { UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel"); } catch (ClassNotFoundException ex) { ex.printStackTrace(); } catch (InstantiationException ex) { ex.printStackTrace(); } catch (IllegalAccessException ex) { ex.printStackTrace(); } catch (UnsupportedLookAndFeelException ex) { ex.printStackTrace(); } /*//Windows風格 try { UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); } catch (ClassNotFoundException ex) { ex.printStackTrace(); } catch (InstantiationException ex) { ex.printStackTrace(); } catch (IllegalAccessException ex) { ex.printStackTrace(); } catch (UnsupportedLookAndFeelException ex) { ex.printStackTrace(); }*/ /* //Windows經典風格 try { UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsClassicLookAndFeel"); } catch (ClassNotFoundException ex) { ex.printStackTrace(); } catch (InstantiationException ex) { ex.printStackTrace(); } catch (IllegalAccessException ex) { ex.printStackTrace(); } catch (UnsupportedLookAndFeelException ex) { ex.printStackTrace(); }*/ } }
到此這篇關於java實現科學計算器的文章就介紹到這了,更多相關java科學計算器內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45