1、事件

(1)与事件相关的几个概念

事件源:发生某个情况(事件)的地方(组件)

事件:描述一种情况,比如:鼠标点击,键盘按下某个键,.......

监听器:用于监控事件的发生;不要在监听器中的事件处理方法内编写耗时操作,否则界面将卡死直至耗时操作完毕;因为在

swing中对UI控制和事件处理是同一个线程中进行

(2)事件委托模型

事件源产生事件,监听器监听事件,并做出相应的处理。以响应按钮点击事件为例,在一个面板中放置3个按钮,添加3个监听器对象

作为按钮的动作监听器。

下例中相关的API:

JButton的API:

JButton(String label) 构造一个按钮,label可看作按钮名

JButton(Icon icon)

JButton(String label, Icon icon)

Container的API:

Component add(Component c) 将组件c添加到该容器中

package GUI_Event;

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;


public class ButtonFrame extends JFrame{
	private JPanel buttonPanel;
	private static final int DEFAULT_WIDTH = 800;
	private static final int DEFAULT_HEIGHT = 600;
	
	public ButtonFrame() {
		setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
		
		//create buttons
		JButton yellowButton = new JButton("Yellow");
		JButton blueButton = new JButton("Blue");
		JButton redButton = new JButton("Red");
		
		buttonPanel = new JPanel();
		
		//add buttons to panel
		buttonPanel.add(yellowButton);
		buttonPanel.add(blueButton);
		buttonPanel.add(redButton);
		
		//add panel to frame
		add(buttonPanel);
		
		//associate actions with buttons
		yellowButton.addActionListener(new ColorAction(Color.YELLOW));
		blueButton.addActionListener(new ColorAction(Color.BLUE));
		redButton.addActionListener(new ColorAction(Color.RED));
	}
	
	/**
	 * 一个监听器,监听多种情况
     *监听器作为内部类,是为了能够容易的访问到buttonPanel
	 */
	private class ColorAction implements ActionListener{
		private Color backgroundColor;
		
		public ColorAction(Color c) {
			backgroundColor = c;
		}
		
		@Override
		public void actionPerformed(ActionEvent e) {
			buttonPanel.setBackground(backgroundColor);
			
		}
	}
	
	
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			@Override
			public void run() {
				JFrame frame = new ButtonFrame();//初始化窗口
				frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置:关闭窗口,则程序退出
				frame.setVisible(true);//显示窗口
			}
		});
	}
}

Java图形程序设计学习(3)

(3)由上面实例理解事件处理机制

1、按钮是事件源,点击按钮是事件;点击按钮的事件是一个动作事件,事件源在点击按钮后,会发送一个ActionEvent对象;

与之相对的还有窗口可以发送WindowEvent对象

2、根据发送的对象不同,需要不同类别的监听器去监听事件源。本例中的ColorAction就需要实现特定的监听器接口

ActionListener接口

3、事件源可以注册一个监听器对象,即安排一个监听器对象去监听事件这个事件源,在注册监听器时,可以通过参数让监听

器实现需要达到的响应事件的效果。本例中就是通过传递Color参数,让监听器实现对应的效果。

(4)对上述实例的解读

1、生成3个按钮,添加到buttonPanel(按钮面板)中,再将按钮面板添加到JFrame(框架)中

2、由于按钮产生的事件类型是动作事件,所以自定义监听器应该实现ActionListener接口

3、每个按钮都需要注册一个ColorAction监听器对象,但是通过其构造方法的参数能够实现对不同按钮产生的相同事件做出不

同的响应

4、ColorAction自定义监听器中,由于实现了ActionListener接口,必须要实现其唯一的actionPerformed(ActionEvent e)方

法,由于其中需要设置buttonPanel的颜色变化,需要访问到这个属性,则令ColorAction为内部类。

(5)对上述实例的改进——lambda表达式

lambda表达式使用的好处是不需要建立一个单独的类,去实现要执行的动作。

lambda表达式使用,比如:exitButton.addActionListener( event -> System.exit(0) );

package GUI_Event;

import java.awt.Color;
import java.awt.EventQueue;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

@SuppressWarnings("serial")
public class ButtonFrame3 extends JFrame{
	private JPanel buttonPanel;
	private static final int DEFAULT_WIDTH = 800;
	private static final int DEFAULT_HEIGHT = 600;
	
	public ButtonFrame3() {
		setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
		buttonPanel = new JPanel();
		this.makeButton("yellow", Color.YELLOW);
		this.makeButton("blue", Color.BLUE);
		this.makeButton("red", Color.RED);
		add(buttonPanel);
	}
	
	public void makeButton(String name, Color backgroundColor) {
		JButton button = new JButton(name);
		buttonPanel.add(button);
		//为当前按钮绑定监听事件
		button.addActionListener(event -> buttonPanel.setBackground(backgroundColor));
	}
	
	
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			@Override
			public void run() {
				JFrame frame = new ButtonFrame3();//初始化窗口
				frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置:关闭窗口,则程序退出
				frame.setVisible(true);//显示窗口
			}
		});
	}
}

改进的点在哪?

改进前,自定义一个监听器类,3个按钮就要实例化3个监听器,还要在监听器中实现响应事件的方法。

改进后,多了makeButton方法,取消了自定义的监听器类,makeButton方法的功能是创建一个按钮,添加到buttonPanel中去,再通

过lambda表达式,将对于事件的响应直接注入到一个监听器中。也就是每调用一次makeButton方法,就会产生一个按钮,并且给这

个按钮绑定一个监听器,监听器的响应事件也写好了。代码更简洁,逻辑更清晰,更加面向对象。

(6)另外一种监听事件

刚刚说了按钮产生的是动作事件,会发出ActionEvent对象,对应的监听器需要实现ActionListener接口,该接口中只有一个方法,是

actionPerformed(ActionEvent e),那么自定义监听器类就只需要实现这一个方法。

但是在另外一种情况下,窗口产生的是窗口事件,发出的是WindowEvent对象,对应的监听器就要实现WindowListener接口,而该

接口中却有7个方法。我们在多数情况下只需要实现其中1-2个方法,就能达到自己要求,但却必须实现其它方法,显得代码冗余。在

这种情况下,我们自定义的监听器可以继承WindowAdapter类,它已经实现了WindowListener接口。这样的类叫做适配器类。

public interface WindowListener{

void windowOpened(WindowEvent e); //在窗口打开后调用该方法

void windowClosing(WindowEvent e);  //在用户发出窗口管理器命令关闭窗口时调用

void windowClosed(WindowEvent e);//在窗口关闭后调用该方法

void windowIconified(WindowEvent e);//窗口图标化后调用该方法

void windowDeiconified(WindowEvent e);//窗口非图标化后调用该方法

void windowActivated(WindowEvent e);//**窗口后调用该方法,只有框架和对话框可以被**

void windowDeactivated(WindowEvent e);//窗口变为未**状态后调用该方法

}

一般结合匿名内部类使用:

//是框架frame产生了窗口事件
frame.addWindowListener(
    new WindowAdapter(){
        public void windowClosing(WindowEvent e){
            if(user agrees)
                System.exit(0);
        }
    }
);

 

相关文章: