一、事件处理机制
(1)事件源:事件源回答事件是由谁发生的,也就是事件发生的场所或者来源,通常是组件的对象,例如按钮JButton、下拉框JComboBox、列表框JList、树JTree等。
(2)事件对象:事件对象主要回答发生了什么事情。事件对象本身封装了包含所发生的各种事件的有效信息,包括事件源对象以及处理该事件所需要的其它各种信息(如鼠标点击时的坐标等),这些有效信息被封装在类AWTEvent或其子类的实例对象中。
所有事件类均在java.awt.event包中,常用的事件类包括ActionEvent、AdjustmentEvent、FocusEvent、InputEvent、KeyEvent、MouseEvent、WindowEvent、ItemEvent、TextEvent等,继承于java.awt.AWTEvent类。
(3)事件监听器:事件监听器主要回答当某个事件发生由谁处理以及怎么处理。一旦注册完成一个事件监听器,它将能接受事件对象并进行处理。
二、监听器接口
要处理某个事件,必须实现某个监听器接口。这类似于交通事故是一种事件对象,而成立交通部门并完善处理制度相当于成立了事件监听器(实现了某个监听器接口),而对外发布公文规定:凡是交通事故即交给该交通部门进行处理,这个过程相当于注册完成事件监听器。
每种类型的事件,都定义了相应的事件处理(监听器)接口,其命名规则是XXXEvent事件对应的事件处理(监听器)接口通常命名为XXXListener。 这相当于整个java体系对每种类型的事件规定了必须成立什么部门进行处理,但如何处理则交给程序员去设计,即编写事件处理程序去覆盖对应接口中的所有方法。
三、编写一个完整的事件处理程序过程
(1)引入系统事件类包:import java.awt.event.*
(2)自定义事件处理类,即加上implements XXXListener,如:
public class MyFrame implements ActionListener {
…
}
(3)注册事件源对象的监听者,即告诉程序一旦发生相应的事件后,由谁处理,如:
public class MyFrame extends JFrame implements ActionListener{
MyFrame(String sTitle){
super(sTitle);
JButton btn=new JButton("确定");
…
btn.addActionListener (this);
…
}
}
这个例子中,btn.addActionListener(this)即注册监听者,它相当于宣布一旦发生点击事件(ActionEvent,对应的事件监听器接口为ActionListener,而MyFrame已经implements了该接口)由this处理,this即为MyFrame。
(4)注册了监听者还不能响应相应的事件,还需要实现监听器接口中的所有方法。例如,在上例中,需加入如下代码:
//实现ActionListener接口中的方法
public void actionPerformed(ActionEvent e) {
...//响应某个动作的代码...
}
四、几个完整的事件处理程序实例
(1)窗体单击按钮事件处理程序
import java.awt.event.* ;//第①步,引入事件包
import java.awt.*;
import javax.swing.*;
//第②步,即声明implements某个监听器接口
public class TestJButtonClick implements ActionListener {//事件监听者与事件源属于同一个类
public TestJButtonClick() {
JFrame f = new JFrame("单击按钮事件");
Container c = f.getContentPane();
JButton b = new JButton("Press Me!");
b.addActionListener(this);//第③步,注册监听者
c.add(b, "Center");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(200, 100);
f.setVisible(true);
}
public void actionPerformed(ActionEvent e) {//第④步,监听者如何监听
//e.getActionCommand()方法返回事件源的名称
JOptionPane.showMessageDialog(null,
"你点击了按钮\"" + e.getActionCommand() + "\"",
"提示",
JOptionPane.INFORMATION_MESSAGE);
}
public static void main(String args[]) {
new TestJButtonClick();
}
}
(2)鼠标事件处理程序
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class MousePanel extends JPanel{
int x_pos,y_pos;
MousePanel(){
//注册鼠标事件监听器,并用匿名类来实现事件处理程序
//注意,必须实现(覆盖)接口中的全部方法,哪怕实现代码一句也没有
addMouseListener(new MouseListener(){
public void mouseClicked(MouseEvent e){}
public void mouseEntered(MouseEvent e){}
public void mouseExited(MouseEvent e){}
public void mouseReleased(MouseEvent e){}
public void mousePressed(MouseEvent e){
x_pos=e.getX();
y_pos=e.getY();
repaint();//本方法会自动触发paintComponent方法的运行
}
});
//注册鼠标移动事件监听器,并用匿名类来实现事件处理程序
addMouseMotionListener(new MouseMotionListener(){
public void mouseDragged(MouseEvent e){}
public void mouseMoved(MouseEvent e){
x_pos=e.getX();
y_pos=e.getY();
repaint();//本方法会自动触发paintComponent方法的运行
}
});
}
//覆盖父类的paintComponent方法以绘制当前鼠标的坐标
protected void paintComponent(Graphics g){
super.paintComponent(g);
g.drawString( "当前位置:[" + x_pos + ", " + y_pos + "]",x_pos, y_pos);
}
}
public class TestMouseListener extends JFrame{
TestMouseListener(){
super("鼠标位置");
setContentPane(new MousePanel());
}
public static void main(String args[ ]){
TestMouseListener f = new TestMouseListener();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(300, 180);
f.setVisible(true);
}
}
(3)键盘事件处理程序
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class TestKeyListener extends JFrame{
TestKeyListener(String sTitle){
super(sTitle);
Container c = getContentPane();
c.setLayout(new GridLayout(4,1,2,2));
//选择角色
JPanel panel1=new JPanel();
panel1.setLayout(new FlowLayout(FlowLayout.LEFT));
panel1.add(new JLabel("选择角色:"));
JComboBox jcb=new JComboBox();
jcb.addItem("教师");
jcb.addItem("学生");
jcb.setSelectedIndex(1);
panel1.add(jcb);
c.add(panel1);
//输入学号
JPanel panel2=new JPanel();
panel2.setLayout(new FlowLayout(FlowLayout.LEFT));
panel2.add(new JLabel("输入学号:"));
FgTextField txtNum=new FgTextField("", 15, true);
panel2.add(txtNum);
c.add(panel2);
//输入密码
JPanel panel3=new JPanel();
panel3.setLayout(new FlowLayout(FlowLayout.LEFT));
panel3.add(new JLabel("输入密码:"));
panel3.add(new JPasswordField("", 15));
c.add(panel3);
//登录按钮
JPanel panel4=new JPanel();
panel4.setLayout(new FlowLayout(FlowLayout.RIGHT));
panel4.add(new JButton("登录"));
panel4.add(new JButton("取消"));
c.add(panel4);
}
public static void main(String args[ ]){
TestKeyListener f = new TestKeyListener("键盘事件");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.pack();
f.setVisible(true);
}
}
//自定义单行文本框,从JTextField继承过来
class FgTextField extends JTextField{
boolean m_bOnlyInteger;//用于指示是否只允许输入整数
FgTextField(String sText, int columns, boolean bOnlyInteger){
super(sText,columns);
m_bOnlyInteger=bOnlyInteger;
addKeyListener(new KeyAdapter(){
public void keyTyped(KeyEvent e){
if(m_bOnlyInteger){
char c=e.getKeyChar();
if(c<'0' | c>'9')
e.consume(); //取消输入
}
}
});
}
}