全局鼠标事件应该怎么加?

一般情况下,我只需要一个全局鼠标事件就可以判断所有可视对象的点击事件了。但是这个全局鼠标事件应该加在哪里呢?

至少有3个(类)对象可以侦听这个事件:

  1. Stage对象;
  2. root对象,就是你的swf的根显示对象;
  3. 自己绘制一个与舞台等大Sprite对象。

那么,加在什么地方合适呢?

Stage是首先被我排除的对象

Stage上的点击事件总是会被侦测到,我不能控制某些“被遮盖”的对象。举个例子:

假设我制作的这个SWF是游戏地图,另外还有一个UI.swf是游戏的UI界面。UI处于地图的上层。在UI窗体上操作的时候,地图是不应该收到单击事件的。因为这种单击事件,会造成地图中玩家的某些行动。但我总是能收到鼠标的事件,且不容易判断当前的点击是否处于窗体上方。

root对象的有趣之处

每个显示对象都有一个root属性。在将其加入到显示列表的时候,root就指向根显示对象。这个根显示对象,对于纯AS项目来说是主Class;对于Flash项目来说,就是文档类或者MainTimeline(取决于你是否定义了文档类)。

如果root中没有任何的内容,那么即使对root进行了侦听,也是没办法得到鼠标事件的。这很容易理解,因为root是空的,它的里面必须有内容,才可以收到单击。

可是,我在root的graphics对象中绘制了图形,依然是没办法收到鼠标事件。

同样的,即使在root中添加的其他的非InteractiveObject(例如Bitmap、Shape等等)显示对象,也无法收到鼠标事件。

还是用一个Sprite来侦听吧

一个普通的Sprite,只需要在其graphics属性中绘制图形,就可以接收到鼠标事件了。如果想禁用鼠标事件,只需要将该sprite的mouseEnabled设置为false就行了。稍稍麻烦一点的就是,在舞台大小变化的时候,需要重绘一下这个Sprite让它适合舞台而已。

让人奇怪的是,既然root也是Sprite(AS项目的主Class是继承Sprite的),为啥就不行呢?

下面是测试用的代码:

 1package
 2{
 3
 4import flash.display.Sprite;
 5import flash.events.MouseEvent;
 6import flash.display.Shape;
 7/**
 8 * 侦测鼠标事件
 9 */
10public class Main extends Sprite
11{
12    public function Main()
13    {
14        this.mouseEnabled = true;
15        this.mouseChildren = true;
16        var __sprite:Sprite = new Sprite();
17        __sprite.graphics.beginFill(0xFF0000);
18        __sprite.graphics.drawRect(0,0,this.stage.stageWidth, this.stage.stageHeight);
19        __sprite.graphics.endFill();
20        //__sprite.mouseEnabled = false;
21        this.addChild(__sprite);
22
23        var __shape:Shape = new Shape();
24        __shape.graphics.beginFill(0x000FF0);
25        __shape.graphics.drawRect(0,0,100, 100);
26        __shape.graphics.endFill();
27        this.addChild(__shape);
28        this.addEventListener(MouseEvent.CLICK, handler_click);
29
30    }
31
32    private function draw():void
33    {
34        this.graphics.beginFill(0);
35        this.graphics.drawRect(0,0,this.stage.stageWidth, this.stage.stageHeight);
36        this.graphics.endFill();
37    }
38
39    private function handler_click($evt:MouseEvent):void
40    {
41        trace(this.mouseX, this.mouseY);
42    }
43}
44}