您的位置:首页 > 产品设计 > UI/UE

JavaSE学习57:GUI编程之事件模型(二)

2016-06-20 22:34 435 查看

一实现两个数求和并且输出结果

利用所学的GUI编程实现上述的要求。

TFMath.java源代码:

<span style="font-size:18px;">import java.awt.*;
import java.awt.event.*;

public class TFMath {
public static void main(String[] args) {
new TFFrame().launchFrame();
}
}

class TFFrame extends Frame{
TextField num1, num2, num3;

public void launchFrame(){
num1 = new TextField(10);
num2 = new TextField(10);
num3 = new TextField(15);
Label lblPlus = new Label("+");
Button btnEqual = new Button("=");

//在等号对象上添加监听器
btnEqual.addActionListener(new MyMonitor(num1.num2,num3));

setLayout(new FlowLayout());
add(num1);
add(lblPlus);
add(num2);
add(btnEqual);
add(num3);
pack();
setVisible(true);
}
}

class MyMonitor implements ActionListener{
TextField num1, num2, num3;

public MyMonitor(TextField num1, TextField num2, TextField num3){
this.num1 = num1;
this.num2 = num2;
this.num3 = num3;
}

public void actionPerformed(ActionEvent e) {
int n1 = Integer.parseInt(num1.getText());
int n2 = Integer.parseInt(num2.getText());
num3.setText("" + (n1+n2));
}
}</span>
运行结果:



对上面的代码进行优化,体现设计模式的门面模式以及调停这模式。

优化后的代码:

<span style="font-size:18px;">import java.awt.*;
import java.awt.event.*;

public class TFMath {
public static void main(String[] args) {
new TFFrame().launchFrame();
}
}

class TFFrame extends Frame{
TextField num1, num2, num3;

public void launchFrame(){
num1 = new TextField(10);
num2 = new TextField(10);
num3 = new TextField(15);
Label lblPlus = new Label("+");
Button btnEqual = new Button("=");

//在等号对象上添加监听器
btnEqual.addActionListener(new MyMonitor(this));

setLayout(new FlowLayout());
add(num1);
add(lblPlus);
add(num2);
add(btnEqual);
add(num3);
pack();
setVisible(true);
}
}

class MyMonitor implements ActionListener{
TFFrame tf = null;

public MyMonitor(TFFrame tf) {
this.tf = tf;
}

public void actionPerformed(ActionEvent e) {
int n1 = Integer.parseInt(tf.num1.getText());
int n2 = Integer.parseInt(tf.num2.getText());
tf.num3.setText("" + (n1+n2));
}
}</span>


我们也可以使用内部类进行代码优化。

优化后的代码:

<span style="font-size:18px;">import java.awt.*;
import java.awt.event.*;

public class TFMath {
public static void main(String[] args) {
new TFFrame().launchFrame();
}
}

class TFFrame extends Frame{
TextField num1, num2, num3;

public void launchFrame(){
num1 = new TextField(10);
num2 = new TextField(10);
num3 = new TextField(15);
Label lblPlus = new Label("+");
Button btnEqual = new Button("=");

//在等号对象上添加监听器
btnEqual.addActionListener(new MyMonitor());

setLayout(new FlowLayout());
add(num1);
add(lblPlus);
add(num2);
add(btnEqual);
add(num3);
pack();
setVisible(true);
}

//内部类MyMonitor
private class MyMonitor implements ActionListener {
public void actionPerformed(ActionEvent e) {
int n1 = Integer.parseInt(num1.getText());
int n2 = Integer.parseInt(num2.getText());
num3.setText("" + (n1+n2));
}
}
}</span>
两个的结果都同第一个结果。

有关于内部类的使用,详细参考:JavaSE入门学习14:Java面向对象之内部类

使用内部类好处:

1)可以方便的访问包装类的成员。

2)可以更清楚的组织逻辑,放置不应该被其它类访问的类进行访问。

何时使用内部类?

该类不允许或不需要其他类进行访问时。

对于上面的代码,我们还可以再进行优化。

TFMathTest.java源代码:

<span style="font-size:18px;">import java.awt.*;
import java.awt.event.*;

public class TFMathTest extends Frame{
TextField num1;
TextField num2;
TextField sum;

public static void main(String[] args){
new TFMathTest().launchFrame();
}

public void launchFrame(){
num1 = new TextField();
num2 = new TextField();
sum = new TextField();
num1.setColumns(10);
num2.setColumns(10);
sum.setColumns(15);
setLayout(new FlowLayout());
//setSize(500, 30);
Label lblPlus = new Label("+");
Button btnEqual = new Button("=");

btnEqual.addActionListener(new MyListener(this));

add(num1);
add(lblPlus);
add(num2);
add(btnEqual);
add(sum);
pack();
setVisible(true);
}
}

class MyListener implements ActionListener{
private TFMathTest tfmt;

public MyListener(TFMathTest tfmt){
this.tfmt = tfmt;
}

public void actionPerformed(ActionEvent e){
String s1 = tfmt.num1.getText();
String s2 = tfmt.num2.getText();
int i1 = Integer.parseInt(s1);
int i2 = Integer.parseInt(s2);
tfmt.sum.setText(String.valueOf(i1 + i2));
}
}</span>


二Graphics类

每个Component都有一个paint(Graphics g)用于实现绘图目的,每次重画该Component时都会自动调用paint()方法。

Graphics类中提供了许多绘图方法,如:

drawRect(int x,int y,int width,int height)

fillRoundRect(int x,int y,int width,int height,int arcWidth,int arcHeight)

更多的方法和用法请查看API文档。

实例:

TestPaint.java源代码:

<span style="font-size:18px;">import java.awt.*;

public class TestPaint {
public static void main(String[] args) {
new PaintFrame().launchFrame();
}
}

class PaintFrame extends Frame {
public void launchFrame() {
setBounds(200,200,640,480);
setVisible(true);
}

public void paint(Graphics g) {
Color c = g.getColor();
g.setColor(Color.red);
g.fillOval(50, 50, 30, 30);
g.setColor(Color.green);
g.fillRect(80,80,40,40);
//恢复原来画笔的颜色
g.setColor(c);
}
}</span>


运行结果:



三鼠标事件适配器

抽象类java.awt.event.MouseAdapter实现类MouseListener接口,可以使用其子类作为MouseEvent的监听器,

只要重写其相应的方法即可。

对于其他的监听器,也有对应的适配器。使用适配器可以避免监听器类定义没有必要的空方法。

机制:repaint()方法中调用了update()方法,而update()方法又调用了paint()方法。

实例:

MyMouseAdapter.java源代码:

<span style="font-size:18px;">import java.awt.*;
import java.awt.event.*;
import java.util.*;

public class MyMouseAdapter{
public static void main(String args[]){
new MyFrame("drawing");
}
}

class MyFrame extends Frame{
ArrayList<Point> points = null;

//构造方法
MyFrame(String s){
super(s);
points = new ArrayList<Point>();
setLayout(null);
setBounds(300,300,400,300);
this.setBackground(new Color(204,204,255));
setVisible(true);
this.addMouseListener(new Monitor());
}

//画圆
public void paint(Graphics g){
Iterator<Point> i = points.iterator();
while(i.hasNext()){
Point p = (Point)i.next();
g.setColor(Color.BLUE);
g.fillOval(p.x,p.y,20,20);
}
}

public void addPoint(Point p){
//向points对象中添加点对象
points.add(p);
}
}

//MouseAdapter类实现了MouseListener接口
class Monitor extends MouseAdapter{
public void mousePressed(MouseEvent e){
MyFrame f = (MyFrame)e.getSource();
f.addPoint(new Point(e.getX(),e.getY());
//进行重画
f.repaint();
}
}</span>


运行结果:

在窗口中点击会画出很多实心小圆



四Window事件

Window事件所对应的事件类为WindowEvent,所对应的事件监听接口为WindowListener。

WindowListener接口定义的方法有:



与WindowListener对应的适配器为WindowAdapter,下面的例子使用了适配器Adapter设计模式。

TestWindowClose.java源代码:

<span style="font-size:18px;">import java.awt.*;
import java.awt.event.*;

public class TestWindowClose{
public static void main(String args[]){
new MyFrame55("Java窗口");
}
}

class MyFrame55 extends Frame{
MyFrame55(String s){
super(s);
setLayout(null);
setBounds(300, 300, 400, 300);
this.setBackground(new Color(204, 204, 255));
setVisible(true);
this.addWindowListener(new MyWindowMonitor());
}
//内部类MyWindowMonitor
//WindowAdapter类实现了WindowListener接口
class MyWindowMonitor extends WindowAdapter{
public void windowClosing(WindowEvent e){
setVisible(false);
System.exit(0);
}
}
}</span>


运行结果:



使用匿名类优化后的代码:

<span style="font-size:18px;">import java.awt.*;
import java.awt.event.*;

public class TestWindowClose{
public static void main(String args[]){
new MyFrame55("Java窗口");
}
}

class MyFrame55 extends Frame{
MyFrame55(String s){
super(s);
setLayout(null);
setBounds(300, 300, 400, 300);
this.setBackground(new Color(204, 204, 255));
setVisible(true);

//使用匿名方法内部类
//WindowAdapter类实现了WindowListener接口
this.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
setVisible(false);
System.exit(-1);
}
});
}
}</span>


匿名内部类

实例

<span style="font-size:18px;">import java.awt.*;
import java.awt.event.*;

/*	范例名称:匿名类在事件处理中的使用
* 	源文件名称:TestAnonymous.java
*	要  点:
*  	1. 匿名类的性质和用法
*	2. 将监听器类定义为匿名类的好处----
*	在内部类的基础上进一步简化了代码
*/
public class TestAnonymous {
Frame f = new Frame("匿名内部类测试");
TextField tf = new TextField(30);
public TestAnonymous(){
f.add(new Label("请按下鼠标左键并拖动"), "North");
f.add(tf, "South");
//使用匿名类
f.addMouseMotionListener(
new MouseMotionAdapter(){
public void mouseDragged(MouseEvent e) {
String s = "鼠标拖动到位置(" + e.getX() + "," + e.getY() + ")";
tf.setText(s);
}
public void mouseMoved(MouseEvent e) { }
}
);
f.setSize(300, 200);
f.setVisible(true);
}

public static void main(String args[]) {
TestAnonymous t = new TestAnonymous();
}
}</span>


运行结果:



TestAnonymous2.java源文件代码:

<span style="font-size:18px;">import java.awt.*;
import java.awt.event.*;

/*	范例名称:匿名类在事件处理中的使用
* 	源文件名称:TestAnonymous2.java
*	要  点:
*	1. 匿名类只能是内部类
*	2. 匿名类的两种创建方式----既可以继承父类、也可以单重实现接口
*/
public class TestAnonymous2 {
Frame f = new Frame("Test");
TextField tf = new TextField(10);
Button b1 = new Button("Start");

public TestAnonymous2(){
f.add(b1,"North");
f.add(tf,"South");

//使用匿名内部类
b1.addActionListener(new ActionListener(){
private int i;
public void actionPerformed(ActionEvent e) {
tf.setText(e.getActionCommand() + ++i);
}
});

//使用匿名内部类
f.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
System.exit(0);
}
});

f.pack();
f.setVisible(true);
}

public static void main(String args[]) {
new TestAnonymous2();
}
}</span>
运行结果:



适用场合:

1)逻辑比较简单;

2)代码比较少;

五键盘事件处理

实例:

<span style="font-size:18px;">import java.awt.*;
import java.awt.event.*;

public class TestKey {
public static void main(String[] args) {
new KeyFrame().launchFrame();
}
}

class KeyFrame extends Frame {
public void launchFrame() {
setSize(400, 300);
setLocation(300,300);
addKeyListener(new MyKeyMonitor());
setVisible(true);
}

//使用内部类
//KeyAdapter类实现了KeyListener接口
class MyKeyMonitor extends KeyAdapter {
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
//按下UP键
if(keyCode == KeyEvent.VK_UP) {
System.out.println("UP");
}
}
}
}</span>


运行结果:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: