本文分享我用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是计算器的一个内存,用来保存临时数据。
操作时,一个动作监听器可以通过传入两个参数,同时对两个输入框进行操作。
至此初步完成制作计算器的项目。