Created
May 10, 2012 04:59
-
-
Save MgaMPKAy/2651111 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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