前面介绍了如何放置和布局组件,从而产生了丰富的界面,但这些界面对用户的操作没有任何深入的响应。如点击右上角的退出,界面没有任何反应等。在AWT编程中,所有用户的操作都必须有一套机制来完成。即GUI事件处理机制,而Frame和组件本身没有事件处理能力。
定义:当在某个组件上发生某个操作的时候,会自动的触发某段代码的执行。
基本概念:
事件源(Event Source):
操作发生的场所,通常是某个组件或窗口。
事件(Event):
在事件源上发生的操作可以叫做事件,GUI会将所有的事件封装到一个Event对象中,如果需要知道该事件的详细信息,就可以通过Event对象来获取。
事件监听器(Event Listener):
对事件源上发生的事件进行处理。
注册监听:
把监听器通过谋个事件绑定到事件源上,当事件源上该事件发生后,监听器中的代码会立即执行。 一般我们希望用户操作后执行的代码都可以写入监听器中。
单击按钮,文本框中显示出Hello World。
代码如下:
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.concurrent.TimeoutException;
public class EventDemo {
Frame frame=new Frame("这里测试事件处理!");
TextField tf=new TextField(30);
//事件源
Button ok=new Button("确定");
public void init(){
//组装视图
MyListener myListener=new MyListener();
//注册监听
//一旦点击ok按钮,就会执行myListener中的代码
ok.addActionListener(myListener);
//把tf和ok放入到Frame中
frame.add(tf,BorderLayout.NORTH);
frame.add(ok);
//调整大小并设置可视化
frame.pack();
frame.setVisible(true);
}
//创建事件监听器
public class MyListener implements ActionListener{
@Override
public void actionPerformed(ActionEvent e) {
tf.setText("Hello World");
}
}
//主函数直接调用init方法
public static void main(String[] args) {
new EventDemo().init();
}
}
AWT把事件划分成两类事件:低级事件和高级事件。
基于某个特定动作的事件。比如点击、进入、拖放等动作的鼠标事件,比如得到焦点、失去焦点的焦点事件。
事件 | 触发事件时机 |
---|---|
ComponentEvent | 组件事件,当组件的尺寸发生改变、位置发生移动、显示/隐藏状态发生改变时 |
ContainerEvent | 容器事件,当容器中添加/删除组件时 |
WindowEvent | 窗口事件,当窗口状态发生改变时(如打开、关闭、最大化、最小化) |
FocusEvent | 焦点事件,失去焦点、得到焦点时 |
KeyEvent | 键盘事件,当按键被按下、松开、单击时触发该事件 |
MouseEvent | 鼠标事件,当进行单击、按下、松开、移动鼠标等操作时触发该事件 |
PaintEvent | 组件绘制事件,该事件是特殊事件,当GUI组件调用update/paint方法展示自身时触发该事件,该事件并非专用于处理事件模型 |
高级事件的触发并不会基于某个特定的动作,而是根据功能含义定义的事件。
事件 | 触发时机 |
---|---|
ActionEvent | 动作事件,当按钮、菜单项被点击,在TextField中按Enter键触发 |
AjustmentEvent | 调节事件,在滑动条上移动滑块以调节数值时触发该事件 |
ItemEvent | 选项事件,当用户选中某项、或取消选中某项时触发该事件 |
TextEvent | 文本事件,当文本框、文本域里的文本发生改变时触发该事件 |
事件 | 对应监听器 |
---|---|
ActionEvent | ActionListener |
ItemEvent | ItemListener |
MouseEvent | MouseMotionListener(鼠标移动)/MouseListener |
KeyEvent | KeyListener |
FocusEvent | FocusListener |
AdjustmentEvent | AdjustmentListener |
ComponentEvent | ComponentListener |
WindowEvent | WindowListener |
ContainerEvent | ContainerListener |
TextEvent | TextListener |
代码举例:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class ListenerDemo {
public static void main(String[] args) {
Frame frame=new Frame("这里测试监听器");
//创建组件(事件源)
//单行文本框
TextField tf=new TextField(30);
//下拉选择框
Choice names=new Choice();
names.add("A");
names.add("B");
names.add("C");
//给文本域添加TextListener 监听内容的变化
tf.addTextListener(new TextListener() {
@Override
public void textValueChanged(TextEvent e) {
String text=tf.getText();
System.out.println("当前文本框中的内容为:"+text);
}
});
//给下拉选择框添加ItemListener,监听条目选项的变化
names.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
Object item=e.getItem();
System.out.println("当前选中的条目为:"+item);
}
});
//给frame注册 ContainerListener监听器,监听容器中组件的添加
frame.addContainerListener(new ContainerAdapter() {
@Override
public void componentAdded(ContainerEvent e) {
Component child=e.getChild();
System.out.println("frame中添加了:"+child);
}
@Override
public void componentRemoved(ContainerEvent e) {
}
});
//添加到frame中
Box hBox=Box.createHorizontalBox();
hBox.add(names);
hBox.add(tf);
frame.add(hBox);
//设置frame最佳大小并可见
frame.pack();
frame.setVisible(true);
}
}
实现窗口退出
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class ListenerDemo2 {
public static void main(String[] args) {
Frame frame=new Frame("这里测试WindowListener");
frame.setBounds(200,200,500,300);
//设置windowListener 监听用户点击X的动作,如果点击X,则关闭窗口。
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
//停止当前程序
System.exit(0);
}
});
frame.setVisible(true);
}
}
GUI中提供了一些特殊的组件来完成一些特定的功能,例如在窗口中展示的菜单。
名称 | 功能 |
---|---|
MenuBar | 菜单条,存放各种菜单选项 |
Menu | 普通的菜单组件,继承自MenuItem,可作为菜单项使用 |
PopupMenu | 右击弹出的菜单组件 |
MenuItem | 菜单项 |
CheckboxMenuItem | 复选框菜单项组件 |
关系:
代码示例1:
通过使用awt菜单组件来完成下图效果:
import java.awt.*;
import java.awt.event.*;
public class SimpleMenu {
//创建窗口
private Frame frame=new Frame("这里测试菜单相关组件");
//创建菜单条
MenuBar menuBar=new MenuBar();
//创建菜单组件
Menu fileMenu=new Menu("文件");
Menu editMenu=new Menu("编辑");
Menu formatMenu=new Menu("格式");
//菜单项组件
MenuItem auto=new MenuItem("自动换行");
MenuItem copy=new MenuItem("复制");
MenuItem paste=new MenuItem("粘贴");
//菜单项组件
MenuItem comment=new MenuItem("注释 ",new MenuShortcut(KeyEvent.VK_Q,true));
MenuItem cancelComment=new MenuItem("取消注释");
TextArea ta=new TextArea(6,40);
public void init(){
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
//组装视图
comment.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
ta.append("您点击了菜单项:"+e.getActionCommand()+"\n");
}
});
formatMenu.add(comment);
formatMenu.add(cancelComment);
editMenu.add(auto);
editMenu.add(copy);
editMenu.add(paste);
editMenu.add(formatMenu);
menuBar.add(fileMenu);
menuBar.add(editMenu);
frame.setMenuBar(menuBar);
frame.add(ta);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
new SimpleMenu().init();
}
}
运行效果:
代码示例2:
通过PopupMenu组件实现下图效果:
import javafx.scene.layout.BorderRepeat;
import java.awt.*;
import java.awt.event.*;
public class PoupMenuTestDemo {
private Frame frame=new Frame("这里测试PopupMenu");
//创建文本域
TextArea ta=new TextArea("我爱编程!!",6,40);
//创建Panel容器
Panel p=new Panel();
//创建PopupMenu
PopupMenu popupMenu=new PopupMenu();
//创建菜单项
MenuItem comment=new MenuItem("注释");
MenuItem cancelComment=new MenuItem("取消注释");
MenuItem copy=new MenuItem("复制");
MenuItem save=new MenuItem("注释");
public void init(){
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
//组装视图
ActionListener listener=new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String actionCommand=e.getActionCommand();
ta.append("您点击了:"+actionCommand+"\n");
}
};
comment.addActionListener(listener);
cancelComment.addActionListener(listener);
copy.addActionListener(listener);
save.addActionListener(listener);
popupMenu.add(cancelComment);
popupMenu.add(comment);
popupMenu.add(copy);
popupMenu.add(save);
p.add(popupMenu);
//设置Panel的大小
p.setPreferredSize(new Dimension(100,200));
//给Panel注册鼠标事件,监听用户释放鼠标的动作,展示菜单
p.addMouseListener(new MouseAdapter() {
@Override
public void mouseReleased(MouseEvent e) {
boolean flg=e.isPopupTrigger();
if(flg){
//显示PopupMenu
popupMenu.show(p,e.getX(),e.getY());
}
}
});
//放置ta和p
frame.add(ta,BorderLayout.NORTH);
frame.add(p, BorderLayout.SOUTH);
//设置frame最佳大小
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
new PoupMenuTestDemo().init();
}
}