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编程之事件模型的主要内容,如果未能解决你的问题,请参考以下文章

JavaSE学习54:GUI编程之几个常用的类

JavaSE学习55:GUI编程之布局管理器

11 - JavaSE之GUI

JavaJavaSE算法之计算器GUI

轻松学习JavaScript二十七:DOM编程学习之事件模型

JavaSE基础(十 二 )---<GUI>标签,文本框,菜单,密码框组件||事件处理,对话框