本文分享我用Java制作计算器的过程。
version 1
JSQFrame.java
import java.awt.FlowLayout; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JTextField; public class JSQFrame extends JFrame { public static void main(String args[]) { /** * 初始化一个界面 */ JSQFrame frame = new JSQFrame(); frame.setTitle("计算器");// 设置标题 frame.setSize(200, 200);// 设置大小 frame.setDefaultCloseOperation(3);// 关闭 frame.setLocationRelativeTo(null);// 设置位置 frame.setResizable(false);// 不可改变大小 /** * 设置布局 */ FlowLayout layout = new FlowLayout(); frame.setLayout(layout); /** * 输入框 */ JTextField valueField = new JTextField("0.", 16); // 初始值为"0.",长度为16字符 /** * 设置内容右对齐 */ valueField.setHorizontalAlignment(JTextField.RIGHT); frame.add(valueField); /** * 禁止编辑输入框 */ valueField.setEditable(false); valueField.setBackground(java.awt.Color.WHITE); String values[] = { "7", "8", "9", "/", "4", "5", "6", "*", "1", "2", "3", "-", "0", ".", "=", "+" }; for (int i = 0; i < values.length; i++) { JButton btn = new JButton(values[i]); frame.add(btn); } frame.setVisible(true); } }
首先初始化一个界面,然后用流式布局进行布局。
设置输入框的大小、底色、文本右对齐、禁止编辑。
定义一个字符串数组,用于保存每个按钮代表的含义。用javax.swing.JButton创建了一批按钮。
frame.setVisible(true); 使我们可以看见窗体。
此时按钮还不能实现功能。
version 2
JSQFrame.java
import java.awt.event.ActionEvent; import javax.swing.JTextField; /** * 计算器的监听器,实现动作监听器接口就必须要重写接口中的所有方法 */ public class JSQListener implements java.awt.event.ActionListener { private JTextField jtf; private float a, b, c; String str = ""; String flag = "+";// 设置初始值为+ /** * 如果重载了构造方法,则默认的无参构造方法失效 */ public JSQListener(JTextField jt) { jtf = jt; } /** * 实现接口中的方法 监听器中的方法是通过实践触发自动调用的 */ public void actionPerformed(ActionEvent e) { /** * 获取事件对象的动作命令 */ String command = e.getActionCommand(); if (command.equals("+") || command.equals("-") || command.equals("/") || command.equals("*") || command.equals("=")) { if (!command.equals("=")) { /** * 获取输入框中的字符串 */ String s1 = jtf.getText(); /** * 将纯数字字符串转成float数字 */ a = Float.parseFloat(s1); /** * 清空str */ str = ""; /** * 储存运算符 */ flag = command; } else { /** * 获取输入框中的字符串 */ String s2 = jtf.getText(); /** * 将寸数字字符串转成float数字 */ b = Float.parseFloat(s2); str = ""; if (flag.equals("+")) { c = a + b; } else if (flag.equals("-")) { c = a - b; } else if (flag.equals("*")) { c = a * b; } else if (flag.equals("/")) { c = a / b; } /** * 将计算的结果显示在输入框中 */ if (c == (int) c) jtf.setText((int) c + ".");// 结果是整数则不用显示十分位数 else jtf.setText(c + "");// c加上字符串则显示的是字符串 } } else { str = str + command; // 将获取到的值写到输入框中 jtf.setText(str); } } }
JSQListener.java
import java.awt.event.ActionEvent; import javax.swing.JTextField; /** * 计算器的监听器,实现动作监听器接口就必须要重写接口中的所有方法 */ public class JSQListener implements java.awt.event.ActionListener { private JTextField jtf; private float a, b, c; String str = ""; String flag = "+";// 设置初始值为+ /** * 如果重载了构造方法,则默认的无参构造方法失效 */ public JSQListener(JTextField jt) { jtf = jt; } /** * 实现接口中的方法 监听器中的方法是通过实践触发自动调用的 */ public void actionPerformed(ActionEvent e) { /** * 获取事件对象的动作命令 */ String command = e.getActionCommand(); if (command.equals("+") || command.equals("-") || command.equals("/") || command.equals("*") || command.equals("=")) { if (!command.equals("=")) { /** * 获取输入框中的字符串 */ String s1 = jtf.getText(); /** * 将纯数字字符串转成float数字 */ a = Float.parseFloat(s1); /** * 清空str */ str = ""; /** * 储存运算符 */ flag = command; } else { /** * 获取输入框中的字符串 */ String s2 = jtf.getText(); /** * 将寸数字字符串转成float数字 */ b = Float.parseFloat(s2); str = ""; if (flag.equals("+")) { c = a + b; } else if (flag.equals("-")) { c = a - b; } else if (flag.equals("*")) { c = a * b; } else if (flag.equals("/")) { c = a / b; } /** * 将计算的结果显示在输入框中 */ if (c == (int) c) jtf.setText((int) c + ".");// 结果是整数则不用显示十分位数 else jtf.setText(c + "");// c加上字符串则显示的是字符串 } } else { str = str + command; // 将获取到的值写到输入框中 jtf.setText(str); } } }
JSQFrame.java 中先设置按钮的动作命令,然后给每个按钮加上动作监听器对象。
JSQListener.java 中重载了构造方法,则默认的无参构造方法失效。
String command = e.getActionCommand(); 获取了按钮的字符串。从而可以进行后续的运算。
然后则是获取输入框中的字符串与运算符号、进行运算及返回结果到输入框。
version 3
这一步是将main函数分离出JSQFrame,从而提高可读性。
JSQFrame.java
import java.awt.FlowLayout; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JTextField; public class JSQFrame extends JFrame { /** * 初始化一个界面 */ public void initFrame() { // JSQFrame frame = new JSQFrame(); this.setTitle("计算器");// 设置标题 this.setSize(200, 200);// 设置大小 this.setDefaultCloseOperation(3);// 关闭 this.setLocationRelativeTo(null);// 设置位置 this.setResizable(false);// 不可改变大小 /** * 设置布局 */ FlowLayout layout = new FlowLayout(); this.setLayout(layout); /** * 输入框 */ JTextField valueField = new JTextField("0.", 16); // 初始值为"0.",长度为16字符 /** * 设置内容右对齐 */ valueField.setHorizontalAlignment(JTextField.RIGHT); this.add(valueField); /** * 禁止编辑输入框 */ valueField.setEditable(false); valueField.setBackground(java.awt.Color.WHITE); String values[] = { "7", "8", "9", "/", "4", "5", "6", "*", "1", "2", "3", "-", "0", ".", "=", "+" }; /** * 创建一个动作监听器对象 */ JSQListener lis = new JSQListener(valueField); for (int i = 0; i < values.length; i++) { JButton btn = new JButton(values[i]); /** * 设置按钮的动作命令 */ btn.setActionCommand(values[i]); this.add(btn); /** * 给每个按钮都加上动作监听器对象 */ btn.addActionListener(lis); } this.setVisible(true); } }
JSQListener.java
import java.awt.event.ActionEvent; import javax.swing.JTextField; /** * 计算器的监听器,实现动作监听器接口就必须要重写接口中的所有方法 */ public class JSQListener implements java.awt.event.ActionListener { private JTextField jtf; private float a, b, c; String str = ""; String flag = "+";// 设置初始值为+ /** * 如果重载了构造方法,则默认的无参构造方法失效 */ public JSQListener(JTextField jt) { jtf = jt; } /** * 实现接口中的方法 监听器中的方法是通过实践触发自动调用的 */ public void actionPerformed(ActionEvent e) { /** * 获取事件对象的动作命令 */ String command = e.getActionCommand(); if (command.equals("+") || command.equals("-") || command.equals("/") || command.equals("*") || command.equals("=")) { if (!command.equals("=")) { /** * 获取输入框中的字符串 */ String s1 = jtf.getText(); /** * 将纯数字字符串转成float数字 */ a = Float.parseFloat(s1); /** * 清空str */ str = ""; /** * 储存运算符 */ flag = command; } else { /** * 获取输入框中的字符串 */ String s2 = jtf.getText(); /** * 将纯数字字符串转成float数字 */ b = Float.parseFloat(s2); str = ""; if (flag.equals("+")) { c = a + b; } else if (flag.equals("-")) { c = a - b; } else if (flag.equals("*")) { c = a * b; } else if (flag.equals("/")) { c = a / b; } /** * 将计算的结果显示在输入框中 */ if (c == (int) c) jtf.setText((int) c + ".");// 结果是整数则不用显示十分位数 else jtf.setText(c + "");// c加上字符串则显示的是字符串 } } else { str = str + command; // 将获取到的值写到输入框中 jtf.setText(str); } } }
Start.java
public class Start { public static void main(String args[]) { /** * 创建窗体对象 */ JSQFrame frame = new JSQFrame(); frame.initFrame(); } }
在分离出主函数的过程中,为了调用frame中的initFrame方法,需要先创建一个frame对象。如果创建对象的代码不从JSQFrame中分离出来,那么就会创建两次对象,导致内存浪费,而且此时在主函数中创建的对象是没有意义的。如果想把创建对象的代码从JSQFrame中分离出来,需要把原先在JSQFrame中的frame变成this即可。
version 4(带内存M的运算器)
JSQFrame.java
import java.awt.FlowLayout; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JTextField; public class JSQFrame extends JFrame { /** * 初始化一个界面 */ public void initFrame() { // JSQFrame frame = new JSQFrame(); this.setTitle("计算器");// 设置标题 this.setSize(400, 240);// 设置大小 this.setDefaultCloseOperation(3);// 关闭 this.setLocationRelativeTo(null);// 设置位置 this.setResizable(false);// 不可改变大小 /** * 设置布局 */ FlowLayout layout = new FlowLayout(); this.setLayout(layout); /** * 输入框 */ JTextField valueField = new JTextField("0.", 34); // 初始值为"0.",长度为16字符 /** * 设置内容右对齐 */ valueField.setHorizontalAlignment(JTextField.RIGHT); this.add(valueField); /** * 禁止编辑输入框 */ valueField.setEditable(false); /** * 设置输入框的背景颜色 */ valueField.setBackground(java.awt.Color.WHITE); /** * M输入框 */ JTextField MField = new JTextField(4); MField.setHorizontalAlignment(JTextField.CENTER); this.add(MField); /** * 禁止编辑M框 */ MField.setEditable(false); /** * 设置M框的背景颜色 */ MField.setBackground(java.awt.Color.LIGHT_GRAY); String values[] = { "MR", "MS", "M+", "M-", "MC", "7", "8", "9", "/", "4", "5", "6", "*", "1", "2", "3", "-", "0", ".", "+", "=" }; /** * 创建一个动作监听器对象 */ JSQListener lis = new JSQListener(valueField,MField); for (int i = 0; i < values.length; i++) { JButton btn = new JButton(values[i]); if (i < 5) { java.awt.Dimension dim = new java.awt.Dimension(60, 30); btn.setPreferredSize(dim); } else { java.awt.Dimension dim = new java.awt.Dimension(90, 30); btn.setPreferredSize(dim); } /** * 设置按钮的动作命令 */ btn.setActionCommand(values[i]); this.add(btn); /** * 给每个按钮都加上动作监听器对象 */ btn.addActionListener(lis); } this.setVisible(true); } }
JSQListener.java
import java.awt.event.ActionEvent; import javax.swing.JTextField; /** * 计算器的监听器,实现动作监听器接口就必须要重写接口中的所有方法 */ public class JSQListener implements java.awt.event.ActionListener { private JTextField jtf, mf; private float a, b, c; private float m = 0; String str = ""; String flag = "+";// 设置初始值为+ /** * 如果重载了构造方法,则默认的无参构造方法失效 */ public JSQListener(JTextField jt, JTextField mf) { jtf = jt; this.mf = mf; } /** * 实现接口中的方法 监听器中的方法是通过实践触发自动调用的 */ public void actionPerformed(ActionEvent e) { /** * 获取事件对象的动作命令 */ String command = e.getActionCommand(); if (command.equals("+") || command.equals("-") || command.equals("/") || command.equals("*") || command.equals("=")) { if (!command.equals("=")) { /** * 获取输入框中的字符串 */ String s1 = jtf.getText(); /** * 将纯数字字符串转成float数字 */ a = Float.parseFloat(s1); /** * 清空str */ str = ""; /** * 储存运算符 */ flag = command; } else { /** * 获取输入框中的字符串 */ String s2 = jtf.getText(); /** * 将纯数字字符串转成float数字 */ b = Float.parseFloat(s2); str = ""; if (flag.equals("+")) { c = a + b; } else if (flag.equals("-")) { c = a - b; } else if (flag.equals("*")) { c = a * b; } else if (flag.equals("/")) { c = a / b; } b=0; /** * 将计算的结果显示在输入框中 */ if (c == (int) c) jtf.setText((int) c + ".");// 结果是整数则不用显示十分位数 else jtf.setText(c + "");// c加上字符串则显示的是字符串 } } else if (command.equals("MR") || command.equals("MS") || command.equals("M+") || command.equals("M-") || command.equals("MC")) { if (command.equals("MR")) { /** * 获取字符串 */ jtf.setText(m + ""); str = ""; } else if (command.equals("MS")) { String ms = jtf.getText(); m = Float.parseFloat(ms); str = ""; mf.setText("M"); } else if (command.equals("MC")) { m = 0; str = ""; mf.setText(""); } else if (command.equals("M+")) { String ms = jtf.getText(); m = m + Float.parseFloat(ms); str = ""; mf.setText("M"); } else if (command.equals("M-")) { String ms = jtf.getText(); m = m - Float.parseFloat(ms); str = ""; mf.setText("M"); } }else { str = str + command; // 将获取到的值写到输入框中 jtf.setText(str); } } }
Start.java
public class Start { public static void main(String args[]){ /** * 创建窗体对象 */ JSQFrame frame =new JSQFrame(); frame.initFrame(); } }
M是计算器的一个内存,用来保存临时数据。
操作时,一个动作监听器可以通过传入两个参数,同时对两个输入框进行操作。
至此初步完成制作计算器的项目。