【问题标题】:Intercepting EventListener ActionScript拦截 EventListener ActionScript
【发布时间】:2013-01-09 11:15:12
【问题描述】:

我正在尝试扩展 Button 类并通过以下方式删除默认 EventListener:

removeEventListener(MouseEvent.CLICK, clickHandler);

然后添加如下内容:

    protected function _clickHandler(event:MouseEvent):void{
        Alert.show("Are you sure about this operation", "Alert", 3, this, execute);
        function execute(e:CloseEvent):void{
            if(e.detail == Alert.YES)
                super.clickHandler(event);
        }
    } 

这样,我将拥有一个默认组件,该组件将触发带有“是”或“否”选项的消息警报,并防止我不得不在触发服务器的每个按钮上编写该组件。不幸的是,它不是那样工作的。

  1. 尝试删除默认函数,并添加我写在监听器上的那个;
  2. 试过直接覆盖clickHandler,还是不行;

编辑:这就是我想要的:当用户单击将在我的应用程序中进行服务调用的按钮时,我总是会弹出一个窗口让他告诉我他是否确定。我想要的是为此构建一个自动组件,如下所示:

package screen{
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.ui.Keyboard;

import mx.controls.Alert;
import mx.controls.Button;
import mx.events.CloseEvent;

public class CommonButton extends Button{
    public function CommonButton(){
        super();
        //removeEventListener(MouseEvent.CLICK, clickHandler)
        //addEventListener(MouseEvent.CLICK, clickHandler);
        addEventListener(KeyboardEvent.KEY_DOWN, function (e:KeyboardEvent):void{
            if(e.altKey == Keyboard.ENTER)
                dispatchEvent(new MouseEvent(MouseEvent.CLICK));
        });
    }

    private var _saveEvent:MouseEvent;
    override protected function clickHandler(event:MouseEvent):void{
        _saveEvent = event;
        event.stopImmediatePropagation();
        Alert.show("Are you sure about this operation", "Alert", 3, this, execute);         
    } 

    private function execute(e:CloseEvent):void{
        if(e.detail == Alert.YES)
            super.clickHandler(_saveEvent);
    }
}
}

然后:

    <mx:Script>
    <![CDATA[
        import mx.controls.Alert;
        private function test():void{
            //if the user clicked No, this method will never be called.
            Alert.show("You clicked YES");
        }
    ]]>
</mx:Script>
<screen:CommonButton click="test()" /> 

最终编辑解决方案:

package screen{
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.ui.Keyboard;

import mx.controls.Alert;
import mx.controls.Button;
import mx.events.CloseEvent;

public class CommonButton extends Button{
    public function CommonButton(){
        super();
        addEventListener(KeyboardEvent.KEY_DOWN, function (e:KeyboardEvent):void{
            if(e.altKey == Keyboard.ENTER)
                dispatchEvent(new MouseEvent(MouseEvent.CLICK));
        });
    }

    private var _stopProp:Boolean = true;
    override protected function clickHandler(event:MouseEvent):void{
        if(_stopProp){
            event.stopImmediatePropagation()
            Alert.show("Are you sure about this operation", "Alert", 3, this, execute);
        }else
            _stopProp = true;

    } 

    private function execute(e:CloseEvent):void{
        if(e.detail == Alert.YES){
            _stopProp = false;
            dispatchEvent(new MouseEvent(MouseEvent.CLICK));
        }
    }
}

}

【问题讨论】:

  • 您能否发布显示您尝试覆盖 clickHandler 的代码?
  • 你指的是 flash.display.SimpleButton 吗?你试图用你的覆盖来改变它的什么功能。您是否尝试先通过对话框拦截其他订阅的事件处理程序?
  • 我希望在确认之前不允许调用 click 方法。基本上,我想将 click 方法存储在类中并强制要求确认,如果用户单击“是”,我会立即进行原始调用。我不想使用不同的属性来做到这一点,我实际上想继续使用“点击”。

标签: actionscript-3 event-handling


【解决方案1】:

为什么还要为此烦恼?只需将您的自定义事件处理程序添加到扩展组件并允许正常的事件处理程序触发即可。您可以将多个处理程序注册到同一个事件。我认为这是一个问题的唯一原因是,如果您将其作为库发布并希望阻止用户自己附加点击处理程序,但您不是。您根本不需要在此处删除或停止默认的点击处理程序。

编辑:这是提问者想要在这里发生的一个例子。

public class AButton extends Button
{
    private var stopProp:Boolean = true;

    public function AButton()
    {
        super();
        this.addEventListener(MouseEvent.CLICK,this.clickHandlers);
    }

    private function clickHandlers( e:MouseEvent ):void{
        if ( stopProp ) {
            e.stopImmediatePropagation();

            trace( "clicked in button" );
            Alert.show( "Continue with event", "Warning!", Alert.YES|Alert.NO, null, this.closeHandler  );
        }
    }

    private function closeHandler( e:CloseEvent ):void {
        if ( e.detail == Alert.YES ) {
            this.stopProp = false;
            this.dispatchEvent( new MouseEvent( MouseEvent.CLICK ) );
            this.stopProp = true;
        }
    }
}

如果stopProp 属性为真,这将阻止事件继续进行。然后它会提示用户。如果用户选择“是”,它会将 stopProp 设置为 false,从按钮重新调度 click 事件,并将 stopProp 重置为 false 以供下次使用。如果他们选择“否”,则不会发生任何事情。

我做了一个快速原型来测试它,它确实有效。

【讨论】:

  • 我想要的正是你所描述的。我想将它作为库发布,开发人员将为按钮定义单击。但在实际调用点击之前,我想询问用户(而不是开发人员)是否确定他选择的操作。如果他确定了,就会进行开发者定义的点击。
  • @MarcoAurélioDeleu 查看我刚刚添加到答案中的代码 sn-p。这应该做你想要的。如果不是,我完全误解了你的要求。
【解决方案2】:

使用 Event 类的 stopImmediatePropagation() 方法。

protected function _clickHandler(event:MouseEvent):void{
    event.stopImmediatePropagation();

    Alert.show("Are you sure about this operation", "Alert", 3, this, execute);
    function execute(e:CloseEvent):void{
        if(e.detail == Alert.YES)
            super.clickHandler(event);
    }
}

【讨论】:

  • StopImmediatePropagation 确实有效,并且永远不会调用 click 方法,而只会调用带有确认的警报。但是没有工作的是 super.clickhandler(event),它没有继续进行调用。
  • 不起作用的原因是因为clickHandler就是这样:一个clickHandler。它具有必须运行的内部函数,但它本身并不调度事件。无论您做什么,该单击处理程序都会运行,因为您的处理程序将在默认处理程序之后运行。因此,通过调用super.clickHandler(event),您实际上是在不需要这样做时运行了两次永恒点击机制。
猜你喜欢
  • 2022-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-22
  • 2023-03-14
  • 2013-06-25
  • 2018-08-09
相关资源
最近更新 更多