AsWing入门教程 2.2 鼠标事件
作者:胡矿
著作权所有,请勿转载
Google Doc
http://docs.google.com/Doc?id=dnp8gdz_30dmhcpf
在上一节当中,我们介绍了普通的事件处理。在这一节我们要介绍如何捕捉鼠标事件、键盘事件和焦点事件。
2.1.1鼠标事件。
在AsWing当中的组件都是Sprite的子类,AsWing组件又可以当作Sprite使用。
图2.2-1是一个简易的涂鸦板。
(图2.2-1)
这个涂鸦板有一个“Undo”按钮,可以删除刚刚绘制的一笔。在鼠标离开框架的时候,整个框架会使用一个模糊滤镜。例2.2-1是完整的程序。
package {
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.filters.BlurFilter;
import flash.geom.Point;
import org.aswing.ASColor;
import org.aswing.AsWingManager;
import org.aswing.BorderLayout;
import org.aswing.Container;
import org.aswing.FlowLayout;
import org.aswing.JButton;
import org.aswing.JFrame;
import org.aswing.JPanel;
import org.aswing.border.LineBorder;
import org.aswing.graphics.Graphics2D;
import org.aswing.graphics.IBrush;
import org.aswing.graphics.Pen;
import org.aswing.graphics.SolidBrush;[SWF (width=600, height=500, frameRate=50)]
public class MouseTest extends Sprite {
private var shapes:Array = new Array();//在定义的时候对 Array 赋初值是一个好习惯
private var pen:Pen = new Pen(ASColor.BLACK, 3);
private var brush:IBrush = new SolidBrush(ASColor.BLACK);
private var lastPoint:Point;
private var drawing:Boolean = false;
private var currentShape:Shape;
private var frame:JFrame;
private var canvas:JPanel;
private var blur:BlurFilter = new BlurFilter();
public function MouseTest() {
super();
this.addEventListener(Event.ADDED_TO_STAGE, this.init);
}
private function init(e:Event) :void {
AsWingManager.initAsStandard(this);
this.frame = new JFrame(this, “Mouse Test”);
this.frame.setSizeWH(540, 400);
var c:Container = this.frame.getContentPane();
this.canvas = new JPanel();
this.canvas.setOpaque(true);
this.canvas.setBackground(new ASColor(0xFFFFFF));
this.canvas.setBorder(new LineBorder());
c.append(this.canvas, BorderLayout.CENTER);var buttonPanel:JPanel = new JPanel(new FlowLayout());
c.append(buttonPanel, BorderLayout.WEST);
var undoBtn:JButton = new JButton(”Undo”);
undoBtn.addEventListener(MouseEvent.CLICK, this.undo);
buttonPanel.append(undoBtn);
this.configure();
this.frame.show();
}
private function configure() :void {
this.canvas.addEventListener(MouseEvent.MOUSE_DOWN, this.onMouseDown);
this.canvas.addEventListener(MouseEvent.MOUSE_UP, this.onMouseUp);
this.canvas.addEventListener(MouseEvent.MOUSE_MOVE, this.onMouseMove);
this.frame.addEventListener(MouseEvent.ROLL_OUT, this.onRollOut);
this.frame.addEventListener(MouseEvent.ROLL_OVER, this.onRollOver);
}
private function undo(e:MouseEvent) :void {
var shape:Shape = this.shapes.pop();
if (shape != null) {
this.canvas.removeChild(shape);
}
}private function onMouseDown(e:MouseEvent) :void {
this.currentShape = new Shape();
this.canvas.addChild(this.currentShape);this.lastPoint = new Point(e.localX, e.localY);
this.drawing = true;
}
private function onMouseUp(e:MouseEvent) :void {
if (this.currentShape != null) {
this.canvas.addChild(this.currentShape);
this.shapes.push(this.currentShape);
}
this.drawing = false;
}
private function onMouseMove(e:MouseEvent) :void {
if (this.drawing) {
var point:Point = new Point(e.localX, e.localY);
var g:Graphics2D = new Graphics2D(this.currentShape.graphics);
g.drawLine(this.pen, this.lastPoint.x, this.lastPoint.y, point.x, point.y);
this.lastPoint = point;
}
}
private function onRollOut(e:MouseEvent) :void {this.drawing = false;
this.frame.filters = [this.blur];
}
private function onRollOver(e:MouseEvent) :void {
this.frame.filters = [];
}
}
}
我们来逐行分析这个程序。
在定义类的时候,我们用了一个[SWF (width=600, height=500, frameRate=50)]标记,这个标记告诉编译器目标SWF的大小是800像素宽,500像素高,帧速是50帧/秒。
笔记:
ActionScript3.0支持标记,除了SWF标记之外,常用的标记还有 [Event] 和 [Embed],在本书的附录当中将会介绍这些常用的标记。
在构造函数当中,我们侦听了一个ADDED_TO_STAGE事件,这个事件会在一个DisplayObject被添加到舞台上的时候被触发。和上一章的例子不同,从这一章开始,我们不再在构造函数当中直接做初始化,而是在ADDED_TO_STAGE事件的事件处理函数(init(Event):void {…})当中做初始化。因为在一个Sprite创建的时候它也许还没有被添加到舞台,这时候,Sprite的stage引用还没有被设置,这时候做初始化有可能会造成一些计算上的错误。所以我们将会在Sprite被添加到舞台上之后再来进行初始化。
注意!
在ADDED_TO_STAGE事件的处理函数当中进行初始化是一个良好的习惯,我们将建议你用这样的习惯。这会使你的程序有更好的兼容性。
我们用一个JPanel作为画布。这是因为JPanel是Sprite的子类,我们可以像操作Sprite一样操作JPanel。JPanel默认是透明的,为了能够在上面绘画,我们把它设为不透明的,并且将背景颜色设为白色(0xFFFFFF)。如下:
this.canvas.setOpaque(true);
this.canvas.setBackground(new ASColor(0xFFFFFF));
为了让画布的边缘更加明显,我们给画布加了边框(Border)。setBorder方法继承自Component,所有的AsWing控件都有这个方法。AsWing支持很多种边框,LineBorder是线状边框。常用作组件边界的标识。默认的LineBorder是直角,黑色,宽度为1像素的矩形线框。如下:
this.canvas.setBorder(new LineBorder());
每一笔的绘制从鼠标按下开始,到鼠标离开画布或者鼠标弹起结束。在鼠标按下的时候,我们新建了一个Shape对象,将这个对象加入到画布的显示队列当中(addChild),如下:
this.currentShape = new Shape();
this.canvas.addChild(this.currentShape);
为了记录绘图的过程,我们把每一笔作为一个Shape对象添加到画布(这时候,JPanel应当被看作是一个Sprite)的最上层。同时把这个Shape的引用加入到一个Array当中。在Undo的时候,我们从这个Array当中取出最新的一笔(Shape)的引用,通过这个引用从画布上删除这一笔。如下:
private function undo(e:MouseEvent) :void {
var shape:Shape = this.shapes.pop();
if (shape != null) {
this.canvas.removeChild(shape);
}
}
练习:
1.给这个画图板添加更多功能,比如绘制矩形、绘制椭圆。
2.你可以把整个绘制过程记录下来,以SVG保存。关于SVG的详细信息,可以参看SVG中国的文档http://www.chinasvg.com/
API:flash.events.Event
- Event.ADDED_TO_STAGE:
在对象被加入到舞台(Stage)的显示队列当中的时候触发这个事件。一般来说,不要在构造函数当中直接初始化,而是在ADDED_TO_STAGE事件的处理函数当中初始化,这样可以避免一些初始化错误,程序的兼容性更强。
API:org.aswing.Component
- setOpaque(b:Boolean):void
组件背景是否不透明,false为透明,true为不透明
- setBackground(c:ASColor):void
设置组件的背景颜色,一般这个方法是和setOpaque配合使用的。只有背景是不透明的情况下才能看到背景颜色。
- setBorder(b:Border):void
设置边框。
API:flash.events.MouseEvent
- MouseEvent.CLICK
常数,鼠标点击事件,一次鼠标点击事件=鼠标按下+鼠标弹起。所以,鼠标按下事件和鼠标弹起事件会和鼠标点击事件一起被触发。
- MouseEvent.MOUSE_DOWN
常数,鼠标按下事件,当鼠标在对象上方按下的时候触发。如果对象被
- MouseEvent.MOUSE_UP
常数,鼠标弹起事件,当鼠标在对象上方弹起的时候触发
- MouseEvent.MOUSE_MOVE
常数,鼠标移动事件,鼠标移动的时候触发。系统底层事件,两次事件之间的周期与帧速无关。
- MouseEvent.ROLL_OUT
常数,鼠标滑出对象事件,鼠标滑出对象的时候触发。
- MouseEvent.ROLL_OVER
常数,鼠标滑入对象事件,鼠标滑入对象进入对象上空区域的时候触发。
- localX:Number
属性,鼠标当前的X坐标,参考系是当前对象的局部坐标系。
- localX:Number
属性,鼠标当前的Y坐标,参考系是当前对象的局部坐标系。
API:flash.filters.BlurFilter
- BlurFilter(blurX:Number=4.0, blurY:Number=4.0, auality:int=1.0)
构造函数,模糊滤镜。
API:flash.display.DisplayObject
- filters:Array
属性,可读可写,滤镜列表,显示对象将依次使用队列当中的滤镜。
API:Array
- pop() :Object
弹出队列尾端的元素(栈顶)。
- push(o:Object) :void
把一个元素加到队列的尾端(栈顶)