3.3 简易计算器的编写&&组合+内部类复习
3.3.1 简易计算器(继承写法)
继承写法,是面向过程的思想!你可能没有察觉到,但确实是面向过程的思想去用面向对象写!
package com.muquanyu.leeson02;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
//简易计算器
public class EasyCalc {
public static void main(String[] args) {
Calculator calculator = new Calculator("简易计算器");
}
}
//计算器类
class Calculator extends Frame{
Calculator(){this("");};
Calculator(String name)
{
super(name);
//三个文本框
TextField textA = new TextField(10);
TextField textB = new TextField(10);
TextField textC = new TextField(10);
//一个标签
Label label = new Label("+");
//一个按钮
Button button = new Button("=");
try{
MyCalculatorListener m = new MyCalculatorListener(textA,textB,textC);
button.setActionCommand("等于按钮");
button.addActionListener(m);
}catch(Throwable e)
{
System.out.println("过滤异常!");
}
setLayout(new FlowLayout(FlowLayout.LEFT));
add(textA);
add(label);
add(textB);
add(button);
add(textC);
setSize(400,100);
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
super.windowClosing(e);
System.exit(0);
}
});
setVisible(true);
};
}
class MyCalculatorListener implements ActionListener {
MyCalculatorListener(){};
private TextField num1,num2,num3;
MyCalculatorListener(TextField num1,TextField num2,TextField num3)
{
this.num1 = num1;
this.num2 = num2;
this.num3 = num3;
};
@Override
public void actionPerformed(ActionEvent e) {
if(num1.getText().isEmpty())
{
num1.setText("0");
}
if(num2.getText().isEmpty())
{
num2.setText("0");
}
int num = Integer.parseInt(num1.getText()) + Integer.parseInt(num2.getText());
num3.setText(Integer.toString(num));
}
}
有一个地方,是我们在 GUI 编程的时候,需要注意的!那就是如何在该组件的事件里,获取到其它组件!并且操作其它组件的方法和属性。
答:很简单!直接把我们需要用到的组件 传递进来!(因为Java里面,并没有全局变量。我们创建出来的组件,作用域都很小,最大的作用域也仅仅是自己的那块类!)
那么我们不如就将,在一个组件的触发事件里操作其它组件的过程,叫做 "组件联动"如何呢?。
该程序的原理:在我们编写的简易计算器里,一个重大的攻克难关就是让 组件之间相互通讯,即 我们点击了 按钮后,会把 第一个输入框的内容和第二个输入框的内容 获取过来!然后 转为整数,进行相加,在将第三个输入框的内容设置为 这个 相加后的结果。
Integer 是 Java 提供的对于整数操作的 “类库”,该类库 有将字符串转为整数的方法,也有将整数转为字符串的方法。这在C/C++中,是必须要自己纯手写算法 才能够实现的事情!
- 在 MyCalculatorListener 有参构造中 获取 其它组件
private TextField num1,num2,num3;
MyCalculatorListener(TextField num1,TextField num2,TextField num3)
{
this.num1 = num1;
this.num2 = num2;
this.num3 = num3;
};
这样,我们就可以很轻松的通过 我们的 自定义事件的有参构造,在进行初始化的时候(即对象创建的时候),就可以 获取到 我们需要 联动的组件。然后我们就可以 在 按钮触发事件方法内部,直接去用 这些 获取到的 组件了。因为 是属于 同一个类,所以可以直接调用!
3.3.2 类与类关系之"组合"
组合是非常重要的!
在OOP 原则中:“组合” 是大于 “继承” 的。
class A extends B{
}
//下面是组合,可以避免不必要的耦合。
class A{
public B b;
}
- 简易计算器(组合版本)比较适合 我们充分理解GUI编程的流程!
package com.muquanyu.leeson02;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class 组合 {
public static void main(String[] args) {
MyCalc calc = new MyCalc("简易计算机(组合)");
}
}
class MyCalc extends Frame {
//我们创建 一个 Frame 框架,需要用到的 组件,就写到 属性里。这类似于全局变量的概念。
//当我们 把整个 窗口对象 获取到的时候,你就可以用该对象的这些 属性 来 对组件进行操作。
public TextField num1,num2,num3;
public Button bth1;
public Label label1;
MyCalc(){this("");};
MyCalc(String name)
{
super(name);
num1 = new TextField();
num2 = new TextField();
num3 = new TextField();
bth1 = new Button("=");
label1 = new Label("+");
add(num1);
add(label1);
add(num2);
add(bth1);
add(num3);
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
super.windowClosing(e);
System.exit(0);
}
});
bthLisener lis = new bthLisener(this);
bth1.addActionListener(lis);
setLayout(new FlowLayout(FlowLayout.LEFT));
setSize(250,100);
setVisible(true);
};
}
class bthLisener implements ActionListener{
//目的是 获取 创建的 计算器 对象
private MyCalc calc = null;
bthLisener(MyCalc calc)
{
//获取到 计算器对象!! 可以对它里面的 所有组件和方法 进行操作了!
this.calc = calc;
}
@Override
public void actionPerformed(ActionEvent e) {
//计算器的 第一个 输入框
if(calc.num1.getText().isEmpty())
{
calc.num1.setText("0");
}
//计算器的 第二个输入框
if(calc.num2.getText().isEmpty())
{
calc.num2.setText("0");
}
int num = Integer.parseInt(calc.num1.getText()) + Integer.parseInt(calc.num2.getText());
calc.num3.setText(Integer.toString(num));
}
}
实际上,在 Java 里,组合的这种方式,是比较适合 GUI 编程的。因为其它的语言,可能有全局变量的概念。当我们创建一个窗口及其窗口的组件的时候,就会把它们存储到全局变量里!这样也方便进行组件之间的通讯。而且也证明了当程序运行的时候 它们确实 实时存在着。
但是 我们 Java 并没有全局变量的概念。Java 是纯面向对象语言,并且Java 处处都是类!那么就只能用 类与类之间的关系 “组合”,来进行 全局变量的伪造。当你把这个 对象获取过来后,就相当于 拿到了 全局变量!而且因为是面向对象,所以拿到了 整体的窗体框架,就相当于 拿到了 所有的组件!!这种编程形式,其实是比 其它语言那种 全局变量的概念,要好很多的。(因为更加的清晰明了,并且体现了GUI的层次性。)
但是这就是 最好的伪造吗?答案:不是哟~
Java 虽然没有全局变量的概念,但这只是针对于 类外的作用域说的,可是你们仔细想想,Java 基本上都是类,类内的属性不就相当于 全局变量吗?emmm ? 所以 内部类的 GUI 编程思想诞生了。
3.3.3 简易计算器(内部类)
内部类,是 Java GUI 编程 最好的一种方式。它能够畅然无阻的访问所有需要访问的 类!!(只要把它包含进来就行)
package com.muquanyu.leeson02;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class 内部类 {
public static void main(String[] args) {
Calc calc = new Calc("简易计算器");
}
}
class Calc extends Frame{
Calc(){this("");};
TextField num1,num2,num3;
Calc(String name){
super(name);
setLayout(new GridLayout(2,1));
num1 = new TextField();
num2 = new TextField();
num3 = new TextField();
Panel panel1 = new Panel(new FlowLayout());
Panel panel2 = new Panel(new FlowLayout());
Label label = new Label("=");
Button bth1 = new Button("+");
Button bth2 = new Button("-");
Button bth3 = new Button("*");
Button bth4 = new Button("/");
bth1.setActionCommand("加法");
bth2.setActionCommand("减法");
bth3.setActionCommand("乘法");
bth4.setActionCommand("除法");
add(panel1);
add(panel2);
panel1.add(num1);
panel1.add(num2);
panel1.add(label);
panel1.add(num3);
panel2.add(bth1);
panel2.add(bth2);
panel2.add(bth3);
panel2.add(bth4);
bth1.addActionListener(new BthLisener());
bth2.addActionListener(new BthLisener());
bth3.addActionListener(new BthLisener());
bth4.addActionListener(new BthLisener());
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
super.windowClosing(e);
System.exit(0);
}
});
setSize(500,500);
setVisible(true);
}
//成员内部类
public class BthLisener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
Button bth = (Button)e.getSource();
int A = Integer.parseInt(num1.getText());
int B = Integer.parseInt(num2.getText());
int C = 0;
switch (bth.getActionCommand())
{
case "加法":
C = A + B;
num3.setText(Integer.toString(C));
break;
case "减法":
C = A - B;
num3.setText(Integer.toString(C));
break;
case "乘法":
C = A * B;
num3.setText(Integer.toString(C));
break;
case "除法":
C = A / B;
num3.setText(Integer.toString(C));
break;
}
}
}
}
成员内部类没啥稀奇的,就是 把 一个类写在一个类里面。然后就可以调用这个大类里面所有的方法和属性了,它们就相通了。