java上机实验
我们使用的教材是《java简明教程(第三版)》- 皮德常
Swing实现计算器
这个上机实验老师要求我们使用Swing制作一个计算器,老师要求我们按照他给定的样式制作,样式如图:

之后就没啥说的了,直接开始秀智商吧。
盲目分析
学过Swing后,我们了解到在JFrame框架上需要添加组件来实现样式,那么我们需要
- JButton组件
- JTextField组件
- JPanel组件
- Container组件
布局实现
差不多这些组件吧,然后我们就开始动手实现,首先我们需要把这个面板元素划分一下,需要俩个JPanel组件来分区,一个用于上面的显示框,另一个用来放置按钮,显示框我们使用BorderLayout
布局,按钮我们使用GridLayout
布局。区块划分差不多如图显示:
源码长这样子:
frame = new subJFrame("Calculator");
contentPane = frame.getContentPane();
// set the result panel
pan1 = new JPanel();
pan1.setLayout(new BorderLayout());
resultText.setHorizontalAlignment(JTextField.CENTER);// 设置文字居中
resultText.setFont(new Font( "",Font.BOLD,20));// 设置文字大小
pan1.add(resultText, BorderLayout.WEST);// 文本框靠左
pan1.add(clear, BorderLayout.EAST);// 清除按钮靠右
pan1.setPreferredSize(new Dimension(0,60));// 设置显示框大小
// set the input panel
pan2 = new JPanel();
pan2.setLayout(new GridLayout(4,7,10,10));
fillComponent(pan2);
// add the elems to the Frame
contentPane.setLayout(new BorderLayout());
contentPane.add(pan1, BorderLayout.NORTH);
contentPane.add(pan2, BorderLayout.CENTER);
frame.setResizable(false);// cannot scale the window
frame.setLocation(300,200);// where it come in
frame.setSize(700, 400);
frame.setVisible(true);
变量定义都设为全局了,所以这里看上去像是弱语言的语法。
对于 subJFrame("Calculator")
这个方法,我们在Swing教程里说过,不过鉴于你们不会去看,我还是在下面写出来吧。
class subJFrame extends JFrame{
public subJFrame(){}
public subJFrame(String title){
super(title);
}
protected void frameInit(){
super.frameInit();
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
}
大概是这样子。错了看编译器报什么错误吧。也可以留言通知我,实在不行。
添加按钮
那么我们怎么定义按钮呢,我们使用JButton数组来实现,搭配String数组来显示按钮文字。代码如下:
final String str[] = {"7","8","9","/","√","cos","x^2+2x+1","4","5","6","*",
"x^2","tan","x^2+y^2","1","2","3","-","1/x","x^3","x^3+y^2",".",
"0","=","+","sin","%","x+x*y"};
JButton buttons[] = new JButton[str.length];
然后呢,我们需要把这些按钮都加入到Container中去,需要一个小循环来添加。如下:
private void fillComponent(Container c) {
for (int i = 0; i < str.length; i++) {
buttons[i] = new JButton(str[i]);
c.add(buttons[i]);
}
}
通过调用该方法来添加按钮,并且在实例化buttons的时候,也把字符串数组str也加入进去,于是按钮就有相应的标码了。顺序是从左到右,从上到下加入。
添加监听
那么,我们组件那些弄好了,就应该添加监听事件了,我们在主类上写implements ActionListener
,然后为buttons和clear按钮添加点击按钮事件监听器,如下面所示,需要小循环:
for (JButton button : buttons) {
button.addActionListener(this);
}
clear.addActionListener(this);
这里说明一下这个循环,估计你们没用过这样的形式的,这意思是定义一个JButton的button来取遍buttons里面的元素,然后为每个button添加监听事件。
重载actionPerformed
我们添加完监听事件后,那么就需要作出响应,需要重载actionPerformed方法,如下复制就好了:
@Override
public void actionPerformed(ActionEvent e) {
String label = e.getActionCommand();
if ("0123456789.+-*/".contains(label)) {
dealNumber(label);
comd += label;
}else if (label.equals(clear.getActionCommand())) {
clearText();
}else {
dealOperator(label);
}
}
这里,我们分为三个情况,一个是点击 数字键 以及 小数点 时,我们调用dealNumber(label)
方法,二是点击 clear按钮 时,调用clearText()
方法,最后点击 其他按钮 时,我们调用dealOperator(label)
。方法功能呢,说实话我不想解释了,自己调用谷歌翻译吧,不行就百度。
处理数字按钮
我们处理数字按钮以及小数点时,需要显示到显示框上,直接上代码吧,懒得说了
private void dealNumber(String label) {
if (firstDigit) {
resultText.setText(label);
} else if ((label.equals("."))) {
resultText.setText(resultText.getText() + ".");
} else if (!label.equals(".")) {
resultText.setText(resultText.getText() + label);
}
firstDigit = false;
}
我们使用了firstDigit变量来表示是否是我们输入的第一个数字。
处理清除
当我们点击C按钮时,需要清除所有东西,至为初始阶段,懒得说。
private void clearText() {
resultText.setText("0");
firstDigit = true;
operator = "=";
resultNum = 0.0;
comd = "";
}
处理运算符
最具影响力的、最具难度力的区域在这里呢,以上都是打打闹闹,我们需要处理剩下的所有运算符,以此来实现加减乘除以及其他运算。所以难度也就在这里。不说了直接打码。
private void dealOperator(String label) {
switch (operator) {
case "√":
resultNum = Math.sqrt(resultNum);
break;
case "x^2":
resultNum *= resultNum;
break;
case "1/x":
if (resultNum == 0.0) {
operateValidFlag = false;
resultText.setText("There is no reciprocal of zero");
} else {
resultNum = 1 / resultNum;
}
break;
case "sin":
resultNum = Math.sin(Math.PI * resultNum / 180);
break;
case "cos":
resultNum = Math.cos(Math.PI * resultNum / 180);
break;
case "tan":
resultNum = Math.tan(Math.PI * resultNum / 180);
break;
case "x^3":
resultNum = Math.pow(resultNum, 3);
break;
case "%":
resultNum %= getNumberFromText();
break;
case "x^2+2x+1":
resultNum = Math.pow(resultNum, 2) + 2 * resultNum + 1;
break;
case "x^2+y^2":
resultNum = Math.pow(resultNum, 2) + Math.pow(getNumberFromText(), 2);
break;
case "x^3+y^2":
resultNum = Math.pow(resultNum, 3) + Math.pow(getNumberFromText(), 2);
break;
case "x+x*y":
resultNum += resultNum * getNumberFromText();
break;
case "=":
if (!comd.isEmpty()) {
resultNum = prase(comd);
comd = "";
}
else
resultNum = getNumberFromText();
break;
default:
}
if (operateValidFlag) {
long t1;
double t2;
t1 = (long) resultNum;
t2 = resultNum - t1;
if (t2 == 0)
resultText.setText(String.valueOf(t1));
else
resultText.setText(String.valueOf(resultNum));
}
operator = label;
firstDigit = true;
operateValidFlag = true;
}
我们通过匹配字符串来识别是哪一个运算符,然后运算。这里需要注意的是,我在计算 加减乘除 时候,我特殊处理了,我通过String comd
来存储我们需要的四则运算,然后调用函数处理这个四则运算。方便我们实现运算顺序问题(例如:2+3*4)。
处理四则运算
上面我们说道,运用comd变量处理四则运算,所以我们用这个变量当作参数传入方法prase(String content)
中,借此来得出四则运算的答案,该方法运用递归的思想,所以有些生涩难懂,不过从简单的comd上手,跟着方法思路走就可以了解到他的精髓。下面贴出代码:
private static double prase(String content){
// Add
int index = content.indexOf("+");
if (index != -1)
return prase(content.substring(0, index)) + prase(content.substring(index + 1));
// subtract
index = content.lastIndexOf("-");
if (index != -1)
return prase(content.substring(0, index)) - prase(content.substring(index + 1));
// multiply
index = content.indexOf("*");
if (index != -1)
return prase(content.substring(0, index)) * prase(content.substring(index + 1));
// divide
index = content.lastIndexOf("/");
if (index != -1)
return prase(content.substring(0, index)) / prase(content.substring(index + 1));
return Double.parseDouble(content);
}
处理右值
在观察了处理运算符后,是不是发现还有一个方法没见过呢,那就是getNumberFromText()
这个方法,这个方法可以称作获取右值,即得到第二个数。事实上,这是个从文本中获取数字的方法。直接上马:
private double getNumberFromText() {
double result = 0;
try {
result = Double.valueOf(resultText.getText());
} catch (NumberFormatException e) {
}
return result;
}
差不多了
写到这里就差不多结束了,这个程序可以说是目前写的最多行的程序,一共200多行,所以得花费一定时间,码字也不容易,希望屏幕前的朋友可以留个言啥的,沙发给你们,空调也准备好。
实验效果
实验效果的话,只要不是非正常输入,一般都是可以得出正确结果的,若果说你硬是要搞我的话,那么我也没办法,你电脑出问题了可别怪我。所以,不要挑战程序的底线,虽然我这样设计出来的计算器BUG比较多,但是正常使用的话,应该是没啥大问题。不行的话,就点清零按钮,一切都好说。
这里说明一下我参考的资料:
小金子博客(四则运算)
程序猿style(框架)
叨叨几句... 3 条评论
代码第十一行加上protected
@太傅
这位水友说的好,表明了他练功发自内心