AsWing入门教程 2.1 事件处理基础
作者:胡矿
著作权所有,请勿转载
Google Doc
http://docs.google.com/Doc?id=dnp8gdz_24ctmwvs
任何Flash的应用都会不断监视敲击键盘、单击鼠标等事件。Flash播放器报告给正在运行的程序。然后程序会决定如何响应这些事件。在Flash8以及以前的时代,可以在影片剪辑里面直接写onXXX的事件处理代码,但是到了ActionScript3.0,这样的操作已经被废止了,对事件的处理都用统一的添加监听器的方式来实现。
事件源(EventDispatcher)拥有自己的方法,允许我们向其注册事件监听器。当事件源产生某个事件时,事件源会向注册在那个事件上的所有监听器发送通知。
在ActionScript3.0当中,所有的事件对象都是从flash.events.Event派生出来的。当然,有的事件类型有自己的子类,比如KeyboardEvent和MouseEvent。AsWing扩展了Event类,定义了许多自己的事件基类org.aswing.event.AWEvent,所有的AsWing自定义事件类都派生自AWEvent类,比如AttachEvent、DragAndDropEvent、FocusKeyEvent等等。
在ActionScript3.0当中,所有的事件源都是从flash.events.EventDispatcher派生出来的。Component类是EventDispatcher类的子类,所以AsWing组件都是事件源。例如,按钮会发送点击事件,而框架能够发送关闭窗口、最小化等窗口事件。
AsWing的事件机制是对ActionScript3.0事件机制的扩展,所以,AsWing的事件处理和ActionScript3.0的事件处理是相容的。
作为总结,下面给出AsWing当中事件处理机制的概览:
-
一个监听器是一个方法。
-
一个事件源是一个扩展了EventDispatcher,能够注册监听器并且向它们发送事件对象的对象。
-
事件发生时,事件源会把事件对象发送给所有注册了这个事件的监听器,一个事件源可以发送多种不同的事件。
-
监听器随后使用事件对象中的信息来决定对事件的反应。
可以使用下面模式的代码为事件源注册监听器:
eventSourceObject.addEventListener(eventType, listener);
例如:
var listener:Function = function (event:Event) : void {
……
};
var button:JButton = new JButton(”OK”);
button.addEventListener(MouseEvent.CLICK, listener);
现在,只要按钮中产生了一个“CLICK”事件,listener方法就会被调用。listener方法接受一个Event类型的参数,其中封装了CLICK事件的相关信息,比如事件所携带的数据,事件的引发者等等。
只要用户按下按钮,JButton对象就会产生一个MouseEvent对象,并且调用listener(event)传递那个事件对象。你可以为一个事件源添加多个监听方法。那样,只要用户按下按钮,所有的监听方法都会被调用。
笔记:
在ActionScript当中,方法(函数)也是对象,可以作为参数传递。
图2.1-1给出了事件源、事件监听函数和事件对象的写作关系。
(图2.1-1)
注意:
在本章中,我们重点关注AsWing的用户界面事件(如按钮点击和鼠标移动事件)的处理。然而,事件处理不仅限于用户界面。
2.1.1 实例:处理按钮点击事件
为了熟悉时间模型,我们使用一个响应按钮点击事件的简单例子来说明模型中所需了解的所有细节。在这个例子中,我们需要:
- 一个放置了3个按钮的面板
- 3个添加到按钮上,作为动作监听器的监听函数
在这个例子中,当用户点击面板上的任何一个按钮时,相关联的监听函数就会收到一个表明按钮被按下的MouseEvent对象。例子中的监听函数随后会改变面板的背景颜色。
在演示程序如何监听按钮点击事件之前,我们首先需要解释如何创建按钮,如何把他们添加到面板上。(有关GUI元素的详细内容,请参考第3章。)
可以通过在按钮的构造器中指定标签字符串、图标,或者二者都指定来创建一个按钮。下面是两个例子:
var button:JButton = new JButton(”Yellow”);
var button:JButton = new JButton(”", new AssetIcon(asset)); // 用一个 asset 作为图标。
把按钮添加到面板需要调用一个称作append的方法(很好记)。append方法的参数为需要添加到容器的组件。例如:
var buttonPanel:JPanel = new JPanel(new FlowLayout());
buttonPanel.setOpaque( true);
var yellowButton:JButton = new JButton(”Yellow”);
var blueButton:JButton = new JButton(”Blue”);
var redButton:JButton = new JButton(”Red”);
buttonPanel.append(yellowButton);
buttonPanel.append(blueButton);
buttonPanel.append(redButton);
图2.1.1-1显示了相应的效果。
在上面的代码中,我们给面板设置了布局管理器(LayoutManager)。组件在添加到面板将会被放在哪里一般是由布局管理器来负责。对于JFrame和JWindow这样的顶层框架来说,默认的布局管理器是边界布局(BorderLayout)。JPanel默认的布局管理器为FlowLayout,在例子当中,我们明确的传入一个FlowLayout实例,你也可以传入其他任何布局管理器实例,FlowLayout是一个很常用的布局管理器,它将组件按照格子的最佳大小绘制,并且从左向右,从上倒下依次顺序排列。关于布局管理器在第3章还会详细叙述。由于默认情况下面板是透明的,我们要对其设置背景颜色就必须让其可见。通过调用buttonPanel.setOpaque(true)让面板变得可见。
现在我们已经布置好了按钮,下面我们要定义3个监听函数,并且分别设为每个按钮的监听函数:
private function __onYellowClick(e:MouseEvent) : void {
}
private function __onBlueClick(e:MouseEvent) : void {
}
private function __onRedClick(e:MouseEvent) : void {
}
yellowButton.addEventListener(MouseEvent.CLICK, this.__onYellowClick);
blueButton.addEventListener(MouseEvent.CLICK, this.__onBlueClick);
redButton.addEventListener(MouseEvent.CLICK, this.__onRedClick);
笔记:
因为在ActionScript当中,函数也是对象,所以监听函数即可以作为类当中的成员函数定义,也可以作为一个局部变量定义,如:
var listenr:Function = function (e:MouseEvent) :void { …… };
现在还遗留有一个问题,就是监听函数没有访问buttonPanel对象的权限。对于这个问题有很多种解决方法,在这里我们想通过我们的这种解决办法告诉大家如何使用事件对象。如下:
private function __onYellowClick(event:MouseEvent) : void {
var button:JButton = event.target as JButton;
var panel:JPanel = button.parent;
panel….
}
这种情况非常常见。事件处理函数往往需要执行一些动作来影响其他的对象。我们当然可以把需要被影响到的对象设为类的成员变量,这样在整个类当中它都将是可以见的。但是如果我们无法看见这个对象的时候,我们通常可以通过事件的发出者来找到所需的对象。event.target就是指向事件的发出者。因为我们把按钮放到了面板当中,所以按钮的父组件(parent)就是面板,于是我们通过button.parent就能得到对面板的引用。
例2.1.1-1包含了完整的程序。只要点击其中的按钮,相应的动作监听函数就会改变面板的背景颜色。
package
{
import flash.display.Sprite;
import flash.events.MouseEvent;
import org.aswing.ASColor;
import org.aswing.AsWingManager;
import org.aswing.Container;
import org.aswing.FlowLayout;
import org.aswing.JButton;
import org.aswing.JFrame;
import org.aswing.JPanel;public class ButtonTest extends Sprite
{
public function ButtonTest()
{
super();
AsWingManager.initAsStandard(this);
var buttonPanel:JPanel = new JPanel(new FlowLayout());
var yellowButton:JButton = new JButton(”Yellow”);
var blueButton:JButton = new JButton(”Blue”);
var redButton:JButton = new JButton(”Red”);
buttonPanel.append(yellowButton);
buttonPanel.append(blueButton);
buttonPanel.append(redButton);
buttonPanel.setOpaque(true);
yellowButton.addEventListener(MouseEvent.CLICK, this.__onYellowClick);
blueButton.addEventListener(MouseEvent.CLICK, this.__onBlueClick);
redButton.addEventListener(MouseEvent.CLICK, this.__onRedClick);
var frame:JFrame = new JFrame(this, “Button Test”);
frame.setSizeWH(300, 250);
var c:Container = frame.getContentPane();
c.append(buttonPanel);
frame.show();
}
private function __onYellowClick(e:MouseEvent) :void {
var button:JButton = e.target as JButton;
var panel:JPanel = button.parent as JPanel;
panel.setBackground(ASColor.YELLOW);
}
private function __onBlueClick(e:MouseEvent) :void {
var button:JButton = e.target as JButton;
var panel:JPanel = button.parent as JPanel;
panel.setBackground(ASColor.BLUE);
}
private function __onRedClick(e:MouseEvent) :void {
var button:JButton = e.target as JButton;
var panel:JPanel = button.parent as JPanel;
panel.setBackground(ASColor.RED);
}
}
}
API:org.aswing.JButton
-
JButton(text:String=”", icon:Icon=null)
构造一个JButton对象,参数text是JButton的标签字符串,是一个普通的纯文本字符串,不支持HTML标记。
icon是按钮的图标。
API:org.aswing.Container
-
append(com:Component):void
把组件com添加到容器中。
API:org.aswing.AssetIcon
-
AssetIcon(asset:DisplayObject=null)
构造一个AssetIcon对象。asset是一个普通的DispalayObject,可以是一个Sprite,一个MovieClip,也可以是一个嵌入swf当中的图形元素