1.AWT事件处理的体系架构
事件可以分为底层事件和语义事件,其中语义事件表示用户动作的事件,底层事件表示形成那些事件的事件
并不是所有的事件都需要注册监听器(Listener)
2.基础
事件处理机制:事件源是一个可以注册监听器和发送事件对象的对象,事件源一般都是相应的组件。监听器对象是一个实现了监听器接口的实例,事件源用addXXXListener()注册监听器后,当事件发生时,事件源发送事件对象至监听器,监听器根据事件对象的信息决定做出何种相应。
class MyListener extends ActionListener
{
public void actionPerformed(ActionEvent e)
{
....
}
}
ActionListener listener = new MyListener();
JButton btn = new JButton();
btn.addActionListener(listener);
当监听器接口是函数式接口时(只有一种抽象方法),可以使用lambda表达式来简化代码
public void makeButton(String name,Color backgroundColor)
{
JButton btn = new JButton(name);
buttonPanel.add(btn);
btn.addActionListener(event->buttonPanel.setBackground(backgroundColor));
}
改变界面观感的方法:
String classname = "com.sun.java.swing.plaf.motif.MotifLookAndFeel";
try
{
UIManager.setLookAndFeel(classname);//参数为观感的类名
SwingUtilities.updateComponentTreeUI(this);//刷新所有的组件集
pack();
}
catch(Exception e) {
e.printStackTrace();
}
列举所有已安装的观感:
UIManager.LookAndFeelInfo[] infos = UIManager.getInstalledLookAndFeels();
其中UIManager.LookAndFeelInfo类有getName()和getClassName()两种方法来得到观感的名称和类名
3.适配器(Adapter)类
有些监听器接口具有多种方法,当只对其中一种方法感兴趣时直接实现接口还需要提供其他方法的实现,十分的不方便,于是出现了适配器类,它为所有的方法都设置为默认方法,则可以通过扩展适配器类来指定某些事件的相应动作,而不需要实现接口中每个方法。
class Terminator extends WindowAdapter//WindowListener具有7种方法
{
public void windowClosing(WindowEvent e)
{
if(...)
System.exit(0);
}
}
但是适配器类有个不足之处,如果在扩展了适配器类的类中添加了一个新的方法,编译器是不会捕捉到这种错误的,可以用@Override放于方法前来避免这种错误。
为了进一步简化代码,可以使用匿名内部类
frame.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e)
{
if(...)
System.exit(0);
}
});
4.动作
Action接口扩展于ActionListener接口,可以时多个组件(如JButton/JMenu/JToolBar)具有相同功能。可实现监听功能。
一个动作封装了:1.命令的说明(一个文本字符(用来表示菜单或按钮的文本标签)和一个可选图标)2.执行命令所需要的参数。可被转换为按钮和菜单项。实际上在JButton的构造方法 public JButton(Action action )中、JToolBar的add(Action action) 、以及JMenu的add(Action action )方法中都可以看出,他们都能够使用Action对象为参数,将Action自动的转化为按钮或者菜单项,你要做的仅仅是定义一个Action对象,之后仅仅需要调用上面的方法就能够自动的将Action转化成组件了。
Action接口的其他方法:
AbstractAction类实现了除actionPerformed(ActionEvent e)的所有方法,因此创建实现了Action接口的类可直接扩展AbstractAction类,并在扩展类中实现actionPerformed
public class colorAction extends AbstractAction//inner class,to use instance field
{
public colorAction(String name,Color c) {
putValue(Action.NAME,name);
putValue("color",c);
putValue(Action.SHORT_DESCRIPTION,"Set panel color to "+name.toLowerCase());
}
public void actionPerformed(ActionEvent event){
buttonPanel.setBackground((Color)getValue("color"));
}
}
用同一个动作响应按钮、菜单项或按键的方法:
1.创建一个AbstractAction类
2.构建动作类对象
3.用动作类对象创建按钮或菜单项,构造器从动作对象中读取标签文本和图标
Action blackAction = new colorAction("Black",Color.BLACK);
buttonPanel.add(new JButton(blackAction));
如果要将快捷键与动作关联起来:
1.得到顶层控件的输入映射(InputMap)
InputMap input = buttonPanel.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
2.为需要的按键创建KeyStrike对象,将(按键,动作键)添加至输入映射(实际上是将按键映射到任意对象上)
input.put(KeyStroke.getKeyStroke("ctrl L"), "black");
3.得到顶层空间的动作映射(ActionMap),将(动作键,动作对象)添加到映射中
ActionMap amap = buttonPanel.getActionMap();
amap.put("black", blackAction);