我希望有一个可重复使用的按钮,可以注册许多不同的回调之一,由外部源决定。设置新的回调时,我想删除旧回调。我也希望能够随时在外部清除回调。
public function registerButtonCallback(function:Function):void
{
clearButtonCallback();
button.addEventListener(MouseEvent.CLICK, function, false, 0, true);
}
public function clearButtonCallback():void
{
if (button.hasEventListener(MouseEvent.CLICK) == true)
{
// do something to remove that listener
}
}
我在这里看到过在回调中使用“arguments.callee”的建议,但我不希望将该功能与回调相关联 - 例如,我可能希望能够单击该按钮两次
建议?
答案 0 :(得分:8)
我假设您在任何给定时间只需要一个回调函数。如果是这种情况那么为什么没有一个回调函数与按钮上的click事件相关联,该按钮本身称为函数并且该函数可以设置...
<mx:Button click="doCallback()" .../>
public var onClickFunction:Function = null;
private function doCallback():void
{
if (onClickFunction != null)
{
onClickFunction(); // optionally you can pass some parameters in here if you match the signature of your callback
}
}
您的控件的消费者将使用适当的函数设置onClickFunction。事实上,你可以随意设置它。
如果你想更进一步,你可以继承AS3 Button类并将其全部包装在其中。
答案 1 :(得分:4)
没有。您需要保持对侦听器的引用才能将其删除。除非您事先存储对侦听器函数的引用,否则没有可用于从EventDispatcher检索此类引用的文档公共方法。
addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void
dispatchEvent(event:Event):Boolean
hasEventListener(type:String):Boolean
removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void
willTrigger(type:String):Boolean
正如您所看到的,有两种方法可以告诉您某种类型的事件是否已注册侦听器,或者其父节点之一是否已注册侦听器,但这些方法实际上都没有返回已注册侦听器的列表。
现在请骚扰Adobe编写这样一个无用的API。基本上,它们使您能够知道“是否”事件流已经改变,但它们无法对该信息做任何事情!
答案 2 :(得分:3)
将侦听器存储为道具。添加另一个事件时,检查侦听器是否存在,如果存在,则调用removeEventListener。
或者,覆盖您按钮的addEventListener方法。调用addEventListener时,在将闭包添加到Dictionary对象中的事件之前存储闭包。再次调用addEventListener时,将其删除:
var listeners:Dictionary = new Dictionary();
override public function addEventListener( type : String, listener : Function, useCapture : Boolean = false, priority : int = 0, useWeakReference : Boolean = false) : void {
if( listeners[ type ] ) {
if( listeners[ type ] [ useCapture ] {
//snip... etc: check for existence of the listener
removeEventListener( type, listeners[ type ] [ useCapture ], useCapture );
listeners[ type ] [ useCapture ] = null;
//clean up: if no listeners of this type exist, remove the dictionary key for the type, etc...
}
}
listeners[ type ] [ useCapture ] = listener;
super.addEventListener( type, listener, useCapture, priority, useWeakReference );
};
答案 3 :(得分:2)
我为此编写了一个名为EventCurb的子类,请在此处查看我的blog或粘贴在下面。
package
{
import flash.events.EventDispatcher;
import flash.utils.Dictionary;
/**
* ...
* @author Thomas James Thorstensson
* @version 1.0.1
*/
public class EventCurb extends EventDispatcher
{
private static var instance:EventCurb= new EventCurb();
private var objDict:Dictionary = new Dictionary(true);
private var _listener:Function;
private var objArr:Array;
private var obj:Object;
public function EventCurb() {
if( instance ) throw new Error( "Singleton and can only be accessed through Singleton.getInstance()" );
}
public static function getInstance():EventCurb {
return instance;
}
override public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void
{
super.addEventListener(type, listener, useCapture, priority, useWeakReference);
}
override public function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void
{
super.removeEventListener(type, listener, useCapture);
}
public function addListener(o:EventDispatcher, type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void {
// the object as key for an array of its event types
if (objDict[o] == null) objArr = objDict[o] = [];
for (var i:int = 0; i < objArr.length; i++) {
if ( objArr[i].type == type)
trace ("_______object already has this listener not adding!")
return
}
obj = { type:type, listener:listener }
objArr.push(obj);
o.addEventListener(type, listener, useCapture, priority, useWeakReference);
}
public function removeListener(o:EventDispatcher, type:String, listener:Function, useCapture:Boolean = false):void {
// if the object has listeners (ie exists in dictionary)
if (objDict[o] as Array !== null) {
var tmpArr:Array = [];
tmpArr = objDict[o] as Array;
for (var i:int = 0; i < tmpArr.length; i++) {
if (tmpArr[i].type == type) objArr.splice(i);
}
o.removeEventListener(type, listener, useCapture);
if (tmpArr.length == 0) {
delete objDict[o]
}
}else {
trace("_______object has no listeners");
}
}
/**
* If object has listeners, returns an Array which can be accessed
* as array[index].type,array[index].listeners
* @param o
* @return Array
*/
public function getListeners(o:EventDispatcher):Array{
if (objDict[o] as Array !== null) {
var tmpArr:Array = [];
tmpArr = objDict[o] as Array;
// forget trying to trace out the function name we use the function literal...
for (var i:int = 0; i < tmpArr.length; i++) {
trace("_______object " + o + " has event types: " + tmpArr[i].type +" with listener: " + tmpArr[i].listener);
}
return tmpArr
}else {
trace("_______object has no listeners");
return null
}
}
public function removeAllListeners(o:EventDispatcher, cap:Boolean = false):void {
if (objDict[o] as Array !== null) {
var tmpArr:Array = [];
tmpArr = objDict[o] as Array;
for (var i:int = 0; i < tmpArr.length; i++) {
o.removeEventListener(tmpArr[i].type, tmpArr[i].listener, cap);
}
for (var p:int = 0; p < tmpArr.length; p++) {
objArr.splice(p);
}
if (tmpArr.length == 0) {
delete objDict[o]
}
}else {
trace("_______object has no listeners");
}
}
}
}
答案 4 :(得分:1)
我喜欢做的事情是使用动态Global类并添加对内联侦听器函数的快速引用。这假设你喜欢像我一样在addEventListener方法中使用监听器函数。这样,您可以在addEventListener :)中使用removeEventListener
试试这个:
package {
import flash.display.Sprite;
import flash.events.Event;
import flash.text.TextField;
[SWF(width="750", height="400", backgroundColor="0xcdcdcd")]
public class TestProject extends Sprite
{
public function TestProject()
{
addEventListener(Event.ADDED_TO_STAGE, Global['addStageEvent'] = function():void {
var i:uint = 0;
//How about an eventlistener inside an eventListener?
addEventListener(Event.ENTER_FRAME, Global['someEvent'] = function():void {
//Let's make some text fields
var t:TextField = new TextField();
t.text = String(i);
t.x = stage.stageWidth*Math.random();
t.y = stage.stageHeight*Math.random();
addChild(t);
i++;
trace(i);
//How many text fields to we want?
if(i >= 50) {
//Time to stop making textFields
removeEventListener(Event.ENTER_FRAME, Global['someEvent']);
//make sure we don't have any event listeners
trace("hasEventListener(Event.ENTER_FRAME) = "+hasEventListener(Event.ENTER_FRAME));
}
});
//Get rid of the listener
removeEventListener(Event.ADDED_TO_STAGE, Global['addStageEvent']);
trace('hasEventListener(Event.ADDED_TO_STAGE) = '+hasEventListener(Event.ADDED_TO_STAGE));
});
}
}
}
//看起来在这里!这是重要的一点 动态类Global {}
秘诀是动态类Global。有了它,您可以在运行时动态添加属性。
答案 5 :(得分:0)
private function callFunction(function:Function):void
{
checkObject();
obj.addEventListener(MouseEvent.CLICK,function);
}
private function checkObject():void
{
if(obj.hasEventListener(MouseEvent.CLICK))
{
//here remove that objects
}
}
答案 6 :(得分:0)
以下内容并未解决删除未知事件侦听器的基本问题,但如果您需要禁用所有与鼠标相关的事件(包括未知事件),请使用: 您的事件目标上的mouseEnabled = false。
这里有更好的东西: http://www.thoughtprocessinteractive.com/blog/the-power-and-genius-of-mousechildren-and-mouseenabled
答案 7 :(得分:0)