1.计算器上的键的显示名字
1.0 继承JFrame类
1 public class Calculate extends JFrame { 2 3 }
1.1定义常量
1 /** 计算器上的键的显示名字 */ 2 3 public final String[] KEYS = { "7", "8", "9", "/", "sqrt", "4", "5", "6", "*", "%", "1", "2", "3", "-", "1/x", "0", "+/-", ".", "+", "=" }; 4 5 /** 计算器上的功能键的显示名字 */ 6 7 public final String[] COMMAND = { "Backspace", "CE", "C" }; 8 9 /** 计算器左边的M的显示名字 */ 10 11 private final String[] M = { " ", "MC", "MR", "MS", "M+" };
1.2 为对应的按键开辟空间
1 /** 计算器上的功能键的按钮 */ 2 3 private JButton commands[] = new JButton[COMMAND.length]; 4 5 /** 计算器左边的M的按钮 */ 6 7 private JButton m[] = new JButton[M.length]; 8 9 /** 计算结果文本框 */ 10 11 private JTextField resultText = new JTextField("0");
1.3 最终效果图:
2 内部布局代码
2.1 按键按钮代码
1 // 初始化计算器上键的按钮,将键放在一个画板内 2 3 JPanel keyPanel = new JPanel(); 4 5 // 用网格布局器,4行,5列的网格,网格之间的水平方向间隔为3个象素,垂直方向间隔为3个象素 6 7 keyPanel.setLayout(new GridLayout(4, 5, 3, 3)); 8 9 for (int i = 0; i < KEYS.length; i++) { 10 11 // 数字放入到按键中 12 13 keys[i] = new JButton(KEYS[i]); 14 15 // 将按键添加到面板 16 17 keyPanel.add(keys[i]); 18 19 // 设置颜色为淡蓝色 20 21 keys[i].setForeground(Color.blue); 22 23 } 24 25 // 运算符键用红色标示,其他键用蓝色表示 26 27 keys[3].setForeground(Color.red); 28 29 keys[8].setForeground(Color.red); 30 31 keys[13].setForeground(Color.red); 32 33 keys[18].setForeground(Color.red); 34 35 keys[19].setForeground(Color.red);
2.2 初始化功能键代码
1 // 初始化功能键,都用红色标示。将功能键放在一个画板内 2 3 JPanel commandsPanel = new JPanel(); 4 5 // 用网格布局器,1行,3列的网格,网格之间的水平方向间隔为3个象素,垂直方向间隔为3个象素 6 7 commandsPanel.setLayout(new GridLayout(1,3,3,3)); 8 9 for(int i = 0; i < COMMAND.length; i++){ 10 11 commands[i] = new JButton(COMMAND[i]); 12 13 commandsPanel.add(commands[i]); 14 15 commands[i].setForeground(Color.red); 16 17 }
2.3 初始化M键代码
1 // 初始化M键,用红色标示,将M键放在一个画板内 2 3 JPanel calmsPanel = new JPanel(); 4 5 calmsPanel.setLayout(new GridLayout(5,1,3,3)); 6 7 for(int i = 0 ; i < M.length; i++){ 8 9 m[i] = new JButton(M[i]); 10 11 calmsPanel.add(m[i]); 12 13 m[i].setForeground(Color.red); 14 15 }
2.3 设置文本框代码
1 // 文本框中的内容采用右对齐方式 2 3 resultText.setHorizontalAlignment(JTextField.RIGHT); 4 5 // 不允许修改结果文本框 6 7 resultText.setEditable(false); 8 9 // 设置文本框背景颜色为白色 10 11 resultText.setBackground(Color.WHITE);
2.4 整体布局代码
1 JPanel panel1 = new JPanel(); 2 3 // 画板采用边界布局管理器,画板里组件之间的水平和垂直 间隔都为3象素 4 5 panel1.setLayout(new BorderLayout(3, 3)); 6 7 panel1.add("Center", keyPanel); 8 9 panel1.add("North",commandsPanel);
1 // 建立一个画板放文本框 2 3 JPanel top = new JPanel(); 4 5 top.setLayout(new BorderLayout()); 6 7 top.add("Center", resultText);
1 // 整体布局 2 3 //画板里组件之间的水平间隔都为3象素,垂直方向上间隔都为5象素 4 5 getContentPane().setLayout(new BorderLayout(3, 5)); 6 7 getContentPane().add("North", top); 8 9 getContentPane().add("Center", panel1); 10 11 getContentPane().add("West", calmsPanel);
2.5 添加事件监听
1 实现ActionListener类,复写actionPerformed方法 2 3 public class Test1 extends JFrame implements ActionListener {... 4 5 //为各按钮添加事件侦听器 6 7 //都使用同一个事件侦听器,即本对象。本类的声明中有implements ActionListener 8 9 for(int i = 0; i < KEYS.length; i++){ 10 11 keys[i].addActionListener(this); 12 13 } 14 15 for(int i = 0; i < COMMAND.length; i++){ 16 17 commands[i].addActionListener(this); 18 19 } 20 21 for(int i = 0; i < M.length; i++){ 22 23 m[i].addActionListener(this); 24 25 } 26 27 }
2.6 处理回退事件
1 /** 处理Backspace键被按下的事件 */ 2 3 private void handleBackspace() { 4 5 //获取文本框的内容 6 7 String text = resultText.getText(); 8 9 int len = text.length(); 10 11 if( len > 0){ 12 13 //表示有数字写入 14 15 text = text.substring(0, len - 1); 16 17 if(text.length() == 0){ 18 19 // 如果文本没有了内容,则初始化计算器的各种值 20 21 resultText.setText("0"); 22 23 }else{ 24 25 resultText.setText(text); 26 27 } 28 29 }
2.7 处理CE按键
1 // 用户按了"CE"键 2 3 resultText.setText("0");
2.8 处理数字
1 定义变量: 2 3 // 标志用户按的是否是整个表达式的第一个数字,或者是运算符后的第一个数字 4 5 private boolean firstDigit = true; 6 7 /** 8 9 * 处理数字键被按下的事件 10 11 */ 12 13 private void handleNumber(String label) { 14 15 //firstDigit 默认是true 16 17 if(firstDigit){ 18 19 //用户按的是第一个是数字 20 21 resultText.setText(label); 22 23 }else if((label.equals(".")) && (resultText.getText().indexOf(".") < 0) ){ 24 25 // 输入的是小数点,并且之前没有小数点,则将小数点附在结果文本框的后面 26 27 resultText.setText(resultText.getText() + "."); 28 29 }else if(! label.equals(".")){ 30 31 // 如果输入的不是小数点,则将数字附在结果文本框的后面 32 33 resultText.setText(resultText.getText() + label); 34 35 } 36 37 // 以后输入的肯定不是第一个数字了 38 39 firstDigit = false; 40 41 }
2.9 处理运算符键被按下的事件
1 0. 设置操作是否正常标志位operateValidFlag = true 2 3 设置中间变量resultNum = 0.0 4 5 设置操作符变量operator = "" 主要数获取当前页显示的数字 6 7 1. "=" 主要是用来显示数字,可以是当前输入的数字, 8 9 也可以是用算后赋值给界面的数字 10 11 2. 赋值当前的操作符号给变量 operator 12 13 3. 设置 firstDigt = true 用于下次界面的显示 14 15 //当前运算的运算符 16 17 private String operator = "="; 18 19 //设置一个标志位,判断是否合法 20 21 private boolean operateValidFlag = true; 22 23 // 计算的中间结果。 24 25 private double resultNum = 0.0; 26 27 * 处理运算符键被按下的事件 28 29 * @param key 30 31 */ 32 33 private void handleOperator(String label) { 34 35 // 除法运算 36 37 if (operator.equals("/")) { 38 39 if (getNumberFromText() == 0.0) { 40 41 // 操作不合法 42 43 operateValidFlag = false; 44 45 resultText.setText("除数不能为零"); 46 47 } else { 48 49 resultNum /= getNumberFromText(); 50 51 } 52 53 // 倒数运算 54 55 } else if (operator.equals("1/x")) { 56 57 if (resultNum == 0.0) { 58 59 operateValidFlag = false; 60 61 resultText.setText("除数不能为零"); 62 63 } else { 64 65 resultNum = 1 / resultNum; 66 67 } 68 69 } else if (operator.equals("+")) { 70 71 // 加法运算 72 73 resultNum += getNumberFromText(); 74 75 } else if (operator.equals("-")) { 76 77 // 减法运算 78 79 resultNum -= getNumberFromText(); 80 81 } else if (operator.equals("*")) { 82 83 // 乘法运算 84 85 resultNum *= getNumberFromText(); 86 87 } else if (operator.equals("sqrt")) { 88 89 // 开方运算 90 91 resultNum = Math.sqrt(resultNum); 92 93 } else if (operator.equals("+/-")) { 94 95 // 正数负数运算 96 97 resultNum = resultNum * (-1); 98 99 } else if (operator.equals("=")) { 100 101 // 赋值运算 102 103 resultNum = getNumberFromText(); 104 105 } 106 107 if(operateValidFlag){ 108 109 // 双精度浮点数的运算 110 111 long t1 ; 112 113 double t2; 114 115 t1 = (long) resultNum; 116 117 t2 = resultNum - t1; 118 119 if(t2 == 0){ 120 121 resultText.setText(String.valueOf(t1)); 122 123 System.out.println("resultText.setText(String.valueOf(t1))" + String.valueOf(t1)); 124 125 }else{ 126 127 resultText.setText(String.valueOf(resultNum)); 128 129 System.out.println("resultText.setText(String.valueOf(resultNum))" + String.valueOf(resultNum)); 130 131 } 132 133 } 134 135 // 运算符等于用户按的按钮 136 137 operator = label; 138 139 firstDigit = true; 140 141 operateValidFlag = true; 142 143 } 144 145 /** 146 147 * 从结果文本框中获取数字 148 149 */ 150 151 private double getNumberFromText() { 152 153 double result = 0; 154 155 result = Double.valueOf(resultText.getText()); 156 157 return result; 158 159 }
2.10 处理 C 按键
1 /** 2 3 * 处理C键被按下的事件 4 5 */ 6 7 private void handleC() { 8 9 // 初始化计算器的各种值 10 11 resultText.setText("0"); 12 13 this.firstDigit = true; 14 15 }
3. 完整代码
1 package test; 2 3 import java.awt.BorderLayout; 4 import java.awt.Color; 5 import java.awt.GridLayout; 6 import java.awt.event.ActionEvent; 7 import java.awt.event.ActionListener; 8 9 import javax.swing.JButton; 10 import javax.swing.JFrame; 11 import javax.swing.JPanel; 12 import javax.swing.JTextField; 13 14 /** 15 * 一个计算器,与Windows附件自带计算器的标准版功能、界面相仿。 但还不支持键盘操作。 16 */ 17 public class Calculator extends JFrame implements ActionListener { 18 /** 计算器上的键的显示名字 */ 19 private final String[] KEYS = { "7", "8", "9", "/", "sqrt", "4", "5", "6", 20 "*", "%", "1", "2", "3", "-", "1/x", "0", "+/-", ".", "+", "=" }; 21 /** 计算器上的功能键的显示名字 */ 22 private final String[] COMMAND = { "Backspace", "CE", "C" }; 23 /** 计算器左边的M的显示名字 */ 24 private final String[] M = { " ", "MC", "MR", "MS", "M+" }; 25 /** 计算器上键的按钮 */ 26 private JButton keys[] = new JButton[KEYS.length]; 27 /** 计算器上的功能键的按钮 */ 28 private JButton commands[] = new JButton[COMMAND.length]; 29 /** 计算器左边的M的按钮 */ 30 private JButton m[] = new JButton[M.length]; 31 /** 计算结果文本框 */ 32 private JTextField resultText = new JTextField("0"); 33 34 // 标志用户按的是否是整个表达式的第一个数字,或者是运算符后的第一个数字 35 private boolean firstDigit = true; 36 // 计算的中间结果。 37 private double resultNum = 0.0; 38 // 当前运算的运算符 39 private String operator = "="; 40 // 操作是否合法 41 private boolean operateValidFlag = true; 42 43 /** 44 * 构造函数 45 */ 46 public Calculator() { 47 super(); 48 // 初始化计算器 49 init(); 50 // 设置计算器的背景颜色 51 this.setBackground(Color.LIGHT_GRAY); 52 this.setTitle("计算器"); 53 // 在屏幕(500, 300)坐标处显示计算器 54 this.setLocation(500, 300); 55 // 不许修改计算器的大小 56 this.setResizable(false); 57 // 使计算器中各组件大小合适 58 this.pack(); 59 } 60 61 /** 62 * 初始化计算器 63 */ 64 private void init() { 65 // 文本框中的内容采用右对齐方式 66 resultText.setHorizontalAlignment(JTextField.RIGHT); 67 // 不允许修改结果文本框 68 resultText.setEditable(false); 69 // 设置文本框背景颜色为白色 70 resultText.setBackground(Color.WHITE); 71 72 // 初始化计算器上键的按钮,将键放在一个画板内 73 JPanel calckeysPanel = new JPanel(); 74 // 用网格布局器,4行,5列的网格,网格之间的水平方向间隔为3个象素,垂直方向间隔为3个象素 75 calckeysPanel.setLayout(new GridLayout(4, 5, 3, 3)); 76 for (int i = 0; i < KEYS.length; i++) { 77 keys[i] = new JButton(KEYS[i]); 78 calckeysPanel.add(keys[i]); 79 keys[i].setForeground(Color.blue); 80 } 81 // 运算符键用红色标示,其他键用蓝色表示 82 keys[3].setForeground(Color.red); 83 keys[8].setForeground(Color.red); 84 keys[13].setForeground(Color.red); 85 keys[18].setForeground(Color.red); 86 keys[19].setForeground(Color.red); 87 88 // 初始化功能键,都用红色标示。将功能键放在一个画板内 89 JPanel commandsPanel = new JPanel(); 90 // 用网格布局器,1行,3列的网格,网格之间的水平方向间隔为3个象素,垂直方向间隔为3个象素 91 commandsPanel.setLayout(new GridLayout(1, 3, 3, 3)); 92 for (int i = 0; i < COMMAND.length; i++) { 93 commands[i] = new JButton(COMMAND[i]); 94 commandsPanel.add(commands[i]); 95 commands[i].setForeground(Color.red); 96 } 97 98 // 初始化M键,用红色标示,将M键放在一个画板内 99 JPanel calmsPanel = new JPanel(); 100 // 用网格布局管理器,5行,1列的网格,网格之间的水平方向间隔为3个象素,垂直方向间隔为3个象素 101 calmsPanel.setLayout(new GridLayout(5, 1, 3, 3)); 102 for (int i = 0; i < M.length; i++) { 103 m[i] = new JButton(M[i]); 104 calmsPanel.add(m[i]); 105 m[i].setForeground(Color.red); 106 } 107 108 // 下面进行计算器的整体布局,将calckeys和command画板放在计算器的中部, 109 // 将文本框放在北部,将calms画板放在计算器的西部。 110 111 // 新建一个大的画板,将上面建立的command和calckeys画板放在该画板内 112 JPanel panel1 = new JPanel(); 113 // 画板采用边界布局管理器,画板里组件之间的水平和垂直方向上间隔都为3象素 114 panel1.setLayout(new BorderLayout(3, 3)); 115 panel1.add("North", commandsPanel); 116 panel1.add("Center", calckeysPanel); 117 118 // 建立一个画板放文本框 119 JPanel top = new JPanel(); 120 top.setLayout(new BorderLayout()); 121 top.add("Center", resultText); 122 123 // 整体布局 124 getContentPane().setLayout(new BorderLayout(3, 5)); 125 getContentPane().add("North", top); 126 getContentPane().add("Center", panel1); 127 getContentPane().add("West", calmsPanel); 128 // 为各按钮添加事件侦听器 129 // 都使用同一个事件侦听器,即本对象。本类的声明中有implements ActionListener 130 for (int i = 0; i < KEYS.length; i++) { 131 keys[i].addActionListener(this); 132 } 133 for (int i = 0; i < COMMAND.length; i++) { 134 commands[i].addActionListener(this); 135 } 136 for (int i = 0; i < M.length; i++) { 137 m[i].addActionListener(this); 138 } 139 } 140 141 /** 142 * 处理事件 143 */ 144 public void actionPerformed(ActionEvent e) { 145 // 获取事件源的标签 146 String label = e.getActionCommand(); 147 if (label.equals(COMMAND[0])) { 148 // 用户按了"Backspace"键 149 handleBackspace(); 150 } else if (label.equals(COMMAND[1])) { 151 // 用户按了"CE"键 152 resultText.setText("0"); 153 } else if (label.equals(COMMAND[2])) { 154 // 用户按了"C"键 155 handleC(); 156 } else if ("0123456789.".indexOf(label) >= 0) { 157 // 用户按了数字键或者小数点键 158 handleNumber(label); 159 // handlezero(zero); 160 } else { 161 // 用户按了运算符键 162 handleOperator(label); 163 } 164 } 165 166 /** 167 * 处理Backspace键被按下的事件 168 */ 169 private void handleBackspace() { 170 String text = resultText.getText(); 171 int i = text.length(); 172 if (i > 0) { 173 // 退格,将文本最后一个字符去掉 174 text = text.substring(0, i - 1); 175 if (text.length() == 0) { 176 // 如果文本没有了内容,则初始化计算器的各种值 177 resultText.setText("0"); 178 firstDigit = true; 179 operator = "="; 180 } else { 181 // 显示新的文本 182 resultText.setText(text); 183 } 184 } 185 } 186 187 /** 188 * 处理数字键被按下的事件 189 * 190 * @param key 191 */ 192 private void handleNumber(String key) { 193 if (firstDigit) { 194 // 输入的第一个数字 195 resultText.setText(key); 196 } else if ((key.equals(".")) && (resultText.getText().indexOf(".") < 0)) { 197 // 输入的是小数点,并且之前没有小数点,则将小数点附在结果文本框的后面 198 resultText.setText(resultText.getText() + "."); 199 } else if (!key.equals(".")) { 200 // 如果输入的不是小数点,则将数字附在结果文本框的后面 201 System.out.println("resultText.getText()" + resultText.getText()); 202 resultText.setText(resultText.getText() + key); 203 System.out.println("resultText.getText()" + resultText.getText() + key); 204 } 205 // 以后输入的肯定不是第一个数字了 206 firstDigit = false; 207 } 208 209 /** 210 * 处理C键被按下的事件 211 */ 212 private void handleC() { 213 // 初始化计算器的各种值 214 resultText.setText("0"); 215 firstDigit = true; 216 operator = "="; 217 } 218 219 /** 220 * 处理运算符键被按下的事件 221 */ 222 private void handleOperator(String key) { 223 System.out.println(operator.equals("/")); 224 if (operator.equals("/")) { 225 System.out.println("进入到除法里面"); 226 // 除法运算 227 // 如果当前结果文本框中的值等于0 228 if (getNumberFromText() == 0.0) { 229 // 操作不合法 230 operateValidFlag = false; 231 resultText.setText("除数不能为零"); 232 } else { 233 System.out.println("resultNum:" + resultNum); 234 resultNum /= getNumberFromText(); 235 System.out.println("resultNum /= getNumberFromText():" + resultNum); 236 237 } 238 } else if (operator.equals("1/x")) { 239 // 倒数运算 240 if (resultNum == 0.0) { 241 // 操作不合法 242 operateValidFlag = false; 243 resultText.setText("零没有倒数"); 244 } else { 245 resultNum = 1 / resultNum; 246 } 247 } else if (operator.equals("+")) { 248 // 加法运算 249 resultNum += getNumberFromText(); 250 } else if (operator.equals("-")) { 251 // 减法运算 252 resultNum -= getNumberFromText(); 253 } else if (operator.equals("*")) { 254 // 乘法运算 255 resultNum *= getNumberFromText(); 256 } else if (operator.equals("sqrt")) { 257 // 平方根运算 258 resultNum = Math.sqrt(resultNum); 259 } else if (operator.equals("%")) { 260 // 百分号运算,除以100 261 resultNum = resultNum / 100; 262 } else if (operator.equals("+/-")) { 263 // 正数负数运算 264 resultNum = resultNum * (-1); 265 } else if (operator.equals("=")) { 266 // 赋值运算 267 resultNum = getNumberFromText(); 268 } 269 if (operateValidFlag) { 270 // 双精度浮点数的运算 271 long t1; 272 double t2; 273 t1 = (long) resultNum; 274 System.out.println(t1); 275 t2 = resultNum - t1; 276 System.out.println(t2); 277 if (t2 == 0) { 278 resultText.setText(String.valueOf(t1)); 279 } else { 280 resultText.setText(String.valueOf(resultNum)); 281 System.out.println("resultText.setText(String.valueOf(resultNum))" + String.valueOf(resultNum)); 282 } 283 } 284 // 运算符等于用户按的按钮 285 operator = key; 286 firstDigit = true; 287 operateValidFlag = true; 288 } 289 290 /** 291 * 从结果文本框中获取数字 292 * 293 * @return 294 */ 295 private double getNumberFromText() { 296 double result = 0; 297 try { 298 result = Double.valueOf(resultText.getText()).doubleValue(); 299 } catch (NumberFormatException e) { 300 } 301 return result; 302 } 303 304 public static void main(String args[]) { 305 Calculator calculator1 = new Calculator(); 306 calculator1.setVisible(true); 307 calculator1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 308 } 309 }