ActionScript - 全局自定义事件?
到目前为止,我需要处理自己的自定义事件的方法是向分派自定义事件的对象添加事件侦听器。虽然这种事件处理方法工作得很好,但我希望我的自定义事件可以全局访问,其中侦听对象不需要与调度事件的对象相同。
在此示例中,我的主要 Controller 类正在实例化并向显示列表添加 2 个精灵类:Square 和三角形。第四个也是最后一个类是一个名为 ColorChangeEvent 的自定义事件。
我正在尝试从 Square 类调度一个新的 ColorChangeEvent,它使用计时器每秒调度一次新的随机颜色,而 Triangle 将侦听调度的事件并将其填充颜色更改为 Square 调度的颜色。
Controller.as:
package
{
import flash.display.Sprite;
public class Controller extends Sprite
{
public function Controller()
{
var sq:Square = new Square();
sq.x = sq.y = 100;
var tr:Triangle = new Triangle();
tr.x = tr.y = 250;
addChild(sq);
addChild(tr);
}
}
}
Square.as:
package
{
import flash.display.Sprite;
import flash.events.TimerEvent;
import flash.utils.Timer;
public class Square extends Sprite
{
public function Square()
{
graphics.beginFill(0x999999);
graphics.drawRect(0, 0, 100, 100);
graphics.endFill();
var myTimer:Timer = new Timer(1000);
myTimer.addEventListener(TimerEvent.TIMER, dispatchNewColor);
myTimer.start();
}
private function dispatchNewColor(evt:TimerEvent):void
{
var randomColor:Number = Math.random() * 0xFFFFFF;
trace("Square Class Dispatched: " + randomColor);
dispatchEvent(new ColorChangeEvent(ColorChangeEvent.CHANGE, randomColor));
}
}
}
Triangle.as:
package
{
import flash.display.Sprite;
import flash.geom.ColorTransform;
public class Triangle extends Sprite
{
public function Triangle()
{
graphics.beginFill(0x999999);
graphics.moveTo(0, 0);
graphics.lineTo(100, 50);
graphics.lineTo(-50, 150);
graphics.endFill();
addEventListener(ColorChangeEvent.CHANGE, changeColor);
}
private function changeColor(evt:ColorChangeEvent):void
{
var ct:ColorTransform = new ColorTransform;
ct.color = evt.color;
transform.colorTransform = ct;
trace("Triangle Class Received: " + evt.color);
}
}
}
ColorChangeEvent.as:
package
{
import flash.events.Event;
public class ColorChangeEvent extends Event
{
public static const CHANGE:String = "change";
public var color:Number;
public function ColorChangeEvent(type:String, color:Number)
{
super(type);
this.color = color;
}
override public function clone():Event
{
return new ColorChangeEvent(type, color);
}
}
}
不用说,这不是不工作。
当然,我可以将事件侦听器添加到 Controller 类中的 Square 实例,该实例的事件处理程序可以通过公共函数将该值传递给 Triangle 以更改颜色,但这正是我试图避免的限制。
访问自定义事件并将其传递给调度自定义事件的类并不总是那么容易,这就是为什么我正在寻找一个实际的全局解决方案来处理自定义事件。
up until now, the way i've been needing to handle my own custom events is by adding an event listener to the object that was dispatching the custom event. while this method of event handling works just fine, i've come to the point where i would like my custom events to be globally accessible, where the listening object does not need to be the same object that is dispatching the event.
in this example, my main Controller class is instantiating and adding to the display list 2 sprite classes: Square and Triangle. the 4th and final class is a custom event called ColorChangeEvent.
i'm attempting to dispatch a new ColorChangeEvent from the Square class, which uses a timer to dispatch a new random color once every second, while Triangle will listen for the dispatched event and change its fill color to the color that was dispatched by Square.
Controller.as:
package
{
import flash.display.Sprite;
public class Controller extends Sprite
{
public function Controller()
{
var sq:Square = new Square();
sq.x = sq.y = 100;
var tr:Triangle = new Triangle();
tr.x = tr.y = 250;
addChild(sq);
addChild(tr);
}
}
}
Square.as:
package
{
import flash.display.Sprite;
import flash.events.TimerEvent;
import flash.utils.Timer;
public class Square extends Sprite
{
public function Square()
{
graphics.beginFill(0x999999);
graphics.drawRect(0, 0, 100, 100);
graphics.endFill();
var myTimer:Timer = new Timer(1000);
myTimer.addEventListener(TimerEvent.TIMER, dispatchNewColor);
myTimer.start();
}
private function dispatchNewColor(evt:TimerEvent):void
{
var randomColor:Number = Math.random() * 0xFFFFFF;
trace("Square Class Dispatched: " + randomColor);
dispatchEvent(new ColorChangeEvent(ColorChangeEvent.CHANGE, randomColor));
}
}
}
Triangle.as:
package
{
import flash.display.Sprite;
import flash.geom.ColorTransform;
public class Triangle extends Sprite
{
public function Triangle()
{
graphics.beginFill(0x999999);
graphics.moveTo(0, 0);
graphics.lineTo(100, 50);
graphics.lineTo(-50, 150);
graphics.endFill();
addEventListener(ColorChangeEvent.CHANGE, changeColor);
}
private function changeColor(evt:ColorChangeEvent):void
{
var ct:ColorTransform = new ColorTransform;
ct.color = evt.color;
transform.colorTransform = ct;
trace("Triangle Class Received: " + evt.color);
}
}
}
ColorChangeEvent.as:
package
{
import flash.events.Event;
public class ColorChangeEvent extends Event
{
public static const CHANGE:String = "change";
public var color:Number;
public function ColorChangeEvent(type:String, color:Number)
{
super(type);
this.color = color;
}
override public function clone():Event
{
return new ColorChangeEvent(type, color);
}
}
}
needless to say, this isn't working.
of course, i could add the event listener to the Square instance in the Controller class, who's event handler could pass that value to Triangle via a public function to change the color, but this is exactly the kind of limitation i'm trying to avoid.
it's not always easy to access and pass a value to a class from where the custom event is dispatched, which is why i'm looking for an actual global solution to handling custom events.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我已经使用这个类有一段时间了。要使用它,您可以在 square: 中执行此操作,
然后在 Triangle: 中执行此
操作,您甚至可以传递
ColorChangeEvent
而不仅仅是颜色。然后
我删除了很多特定于我的项目的代码,所以我不能 100% 完全按原样使用它。但是,您应该能够修改它以使其正常工作。如果没有,请告诉我,我可以尝试与您一起解决。
本课程处理其他我不会讨论的事情,但您可以自由探索。但请注意,任何订阅事件通知的内容都会受到 EventManager 的强引用。这意味着,如果您想销毁某些内容以进行垃圾回收,则需要在收集 Triangle 实例之前调用 EventManager.instance.cancel(ColorChangeEvent.CHANGE, handleColorChange)。
I have been using this class for some time now. To use it you would do this in square:
and then in your Triangle:
You can even pass the
ColorChangeEvent
instead of just the color.And then
I removed a lot of code that is specific to my projects, so I am not 100% it is usable exactly as-is. But, you should be able to modify it to get it working correctly. If not, let me know and I can try to work it out with you.
This class handles additional things that I will not go into, though you are free to explore. Be aware, however, that anything that subscribes for event notification has a strong reference by the EventManager. That means that if you want to destroy something for garbage collection, you need to call
EventManager.instance.cancel(ColorChangeEvent.CHANGE, handleColorChange)
before the Triangle instances can be collected.我通过创建一个扩展 EventDispatcher 的单例来实现此目的:
EventDispatchSingleton
。它基本上是一个空的单例,提供了dispatchEvent和add/removeEventListener方法(这些方法是通过扩展EventDispatcher自动提供的)。在任何想要分派事件的地方,我都会导入 EventDispatchSingleton,然后调用
EventDispatchSingleton.instance.dispatchEvent();
。然后,无论我想在哪里监听该事件,我只需导入 EventDispatchSingleton 并调用 EventDispatchSingleton.instance.addEventListener(eventName, callback);
I got this to work by creating a singleton:
EventDispatchSingleton
thatextends EventDispatcher
. It's basically an empty singleton that provides the dispatchEvent and add/removeEventListener methods (these are automatically provided by extending EventDispatcher).Anywhere I want to dispatch an event I import EventDispatchSingleton and then call
EventDispatchSingleton.instance.dispatchEvent(<someEvent>);
.Then, wherever I want to listen to that event, I just import EventDispatchSingleton and call
EventDispatchSingleton.instance.addEventListener(eventName, callback);
您应该研究事件冒泡,具体来说,我认为您会发现事件传播的捕获阶段很有用。阅读Adobe LiveDocs 中的事件传播 。它位于 Flex 文档中,但它是关于 AS3 事件的。
另外Senulous 有一篇关于 Flash 事件冒泡的好文章。
You should look into event bubbling, specificly I think you will find the Capturing phase of the event propagation useful. Take a read of Event propagation from Adobe LiveDocs. It's in the Flex docs, but it is about AS3 Events.
Also Senocular has a good post on Flash Event Bubbling.