Skip to content

Instantly share code, notes, and snippets.

@MgaMPKAy
Created May 10, 2012 04:59
Show Gist options
  • Save MgaMPKAy/2651111 to your computer and use it in GitHub Desktop.
Save MgaMPKAy/2651111 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html>
<head>
<title>Calc</title>
</head>
<body>
<APPLET code="Calc.class" WIDTH="400" HEIGHT="300">
This is where HelloWorld.class runs.</APPLET></P>
</body>
</html>
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.JApplet;
public class Calc extends JApplet {
// 文本框
private JTextField numField;
// 数字按钮,NumButton是JButton子类,Calc内部类
private NumButton[] numButtons;
// 运算按钮,OperationButton是JButton子类,Calc内部类
private OperationButton[] opButtons;
// 前一个输入
private double preInput;
// 前一个运算,运算按钮使用Operation接口
private Operation preOp;
// 标记输入开始,用于一元个负号
private boolean begin = true;
// 记录操作数个数
private int count;
// 在够造函数里建GUI, 只使用了FlowLayout,把个元件设置大小后依次放入
public Calc() {
super();
Container contentPane = getContentPane();
contentPane.setLayout(new FlowLayout());
setPreferredSize(new Dimension(400, 300));
createOperationButtons();
createNumButtons();
numField = new JTextField();
numField.setPreferredSize(new Dimension(380, 30));
add(numField);
for (int i = 0; i <= 9; i++) {
numButtons[i].setPreferredSize(new Dimension(120, 30));
add(numButtons[i]);
}
for (int i = 0; i <= 5; i++) {
opButtons[i].setPreferredSize(new Dimension(120, 30));
add(opButtons[i]);
}
setVisible(true);
}
// 建数字按钮
void createNumButtons() {
numButtons = new NumButton[10];
for (int i = 0; i <= 9; i++) {
numButtons[i] = new NumButton(i);
}
}
// 建运算按钮
void createOperationButtons() {
opButtons = new OperationButton[6];
// 加法按钮, 使用匿名的Operation
opButtons[0] = new OperationButton("+", new Operation() {
public double eval() {
return preInput + getInput();
}
});
opButtons[1] = new OperationButton("-", new Operation() {
public void performedOP() {
// 减法也可以当作一元运算,特殊处理
if (begin) {
numField.setText("-" + numField.getText());
begin = false;
count = 0;
return;
}
if (count == 0) {
if (numField.getText().equals("")) {
return;
}
preInput = getInput();
preOp = this;
count = 1;
} else if (count == 1) {
preOp = this;
} else {
double result = preOp.eval();
numField.setText(result + "");
preInput = result;
preOp = this;
count = 1;
}
begin = true;
}
public double eval() {
return preInput - getInput();
}
});
opButtons[2] = new OperationButton("*", new Operation() {
public double eval() {
return preInput * getInput();
}
});
opButtons[3] = new OperationButton("/", new Operation() {
public double eval() {
return preInput / getInput();
}
});
// 等号,执行前一个运算
opButtons[4] = new OperationButton("=", new Operation() {
public double eval() {
return getInput();
}
});
// 清空操作,重置状态
opButtons[5] = new OperationButton("Clear", new Operation() {
public void performedOP() {
numField.setText("");
begin = true;
preInput = 0;
count = 0;
preOp = null;
}
public double eval() {
return getInput();
}
});
}
private class OperationButton extends JButton implements ActionListener {
private String name;
Operation op;
OperationButton(String name, Operation op){
super();
this.name = name;
this.setText(name);
this.op = op;
this.addActionListener(this);
}
public void actionPerformed(ActionEvent e) {
op.performedOP();
debug();
}
}
// 数字按钮,
private class NumButton extends JButton implements ActionListener {
private String name;
NumButton(int i) {
super();
this.name = i + "";
this.setText(name);
this.addActionListener(this);
}
public void actionPerformed(ActionEvent e) {
// 如果这是第二个操作数的输入
if (preOp != null && count == 1) {
numField.setText("");
count = 2;
}
// 设beign为假,表示已经有输入
if (begin) {
begin = false;
}
// 显示输入
numField.setText(numField.getText() + name);
debug();
}
}
// Operation接口
// 每个运算按钮都使用Operation接口,把按钮的表现和操作逻辑的实现分开
private class Operation {
// 执行各种逻辑判断、GUI和状态更新
public void performedOP() {
// 当一个操做数都没有的时候
if (count == 0) {
// 如果文本框为空,不用执行运算
if (numField.getText().equals("")) {
return;
}
// 如果文本框不空,则把输入当作第一个操作数
preInput = getInput();
// 记录运算
preOp = this;
count = 1;
} else if (count == 1) {
// 已经有第一个操作数,表示切换运算
// 输入1 +, 再按*, 表示 1 *
preOp = this;
} else {
// 已经有两个操作数
// 掉用前一个运算
// 因为输入1 * 1 + 时,调用的是 * , 并把结果做为第一个操作数
// 变成 1 +
double result = preOp.eval();
numField.setText(result + "");
preInput = result;
preOp = this;
count = 1;
}
begin = true;
}
// 计算数值结果
double eval() {
return 0;
}
}
// 辅助方法,从输入框获得数字
private double getInput() {
double result;
try {
result = java.lang.Double.parseDouble(numField.getText());
} catch (Exception e) {
numField.setText("Error, please clear input");
result = 0;
}
return result;
}
// 调试用,输出各种状态
private void debug() {
System.out.println("count: " + count);
System.out.println("preInput: " + preInput);
System.out.println("currentInout:" + numField.getText());
System.out.println("");
}
// 毫无特色的主函数
public static void main(String[] args) {
new Calc();
}
}
// 思路:同系统自带的计算器
// 问题: 布局太简单, 全局状态维护太负责
//
// 通过Operation类可以方便的实现各种运算,普通的二元运算只要覆盖eval()方法。一元和其他操作要覆盖performedOP(),全局状态维护太负责, 要要考虑不同情况(要考虑没操作数、一个操作数、两个操作数,是否有输入)来修改状态,可以再把Operation接口扩展,把各种状态下的操作分开,而不是单独放在performedOP。
// 同时也可以把运算按钮分为一元和二元的。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment