JavaSE学习57:GUI编程之事件模型
Posted life is wonderful
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaSE学习57:GUI编程之事件模型相关的知识,希望对你有一定的参考价值。
一实现两个数求和并且输出结果
利用所学的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>
运行结果:
以上是关于JavaSE学习57:GUI编程之事件模型的主要内容,如果未能解决你的问题,请参考以下文章