as3 如何调度特定的键盘事件

as3 How to dispatch a specific keyboard event

我当时looking for this answer and had no luck. One place I looked居然有一个很气馁的回答:"You cannot force mouse or keyboard events - they HAVE TO come from mouse or keyboard."

嗯?

我尝试了 'brute force' 并提出了这个解决方案。也许我的做法是错误的或愚蠢的;有没有更好的办法?

我有一个启动 class 的键盘事件,我想在舞台上放置一个 sprite 来启动相同的操作——单击 sprite 将启动键盘事件(退出键)。

在eventListener函数中,我traced事件e本身:

    private function keys(e:KeyboardEvent):void {
        trace("EscapeKey: ",e);   
        if (e.keyCode == 27) {
        ...    
        }
    }

输出是

EscapeKey: [KeyboardEvent type="keyDown" bubbles=true cancelable=false eventPhase=2 charCode=27 keyCode=27 keyLocation=0 ctrlKey=false altKey=false shiftKey=false]    

然后我让 mouseClick 侦听器使用我从上述跟踪中获得的值创建并发送一个新的 keyboardEvent:

    private function pauseClick(e:MouseEvent):void {
        var a:KeyboardEvent = new KeyboardEvent("keyDown", true, false, 27, 27, 0, false, false, false);
        stage.dispatchEvent(a);
    }

转瞬即逝!
希望这个 post 对寻找这些类型的 mouse/keyboard 事件冗余的其他人会派上用场。

编辑 ---评论中要求的完整class示例:

package{
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.events.KeyboardEvent;

    public class KeyboardMouse extends Sprite {
        private var pauseInfo:PauseInfo;

        private var escapeKey:EscapeKey;

        public function KeyboardMouse() {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }

        private function init(e:Event = null):void {
            removeEventListener(Event.ADDED_TO_STAGE, init);

            stage.addEventListener(KeyboardEvent.KEY_DOWN, keys);

            escapeKey = new EscapeKey();
            stage.addChild(escapeKey);

            pauseInfo = new PauseInfo();
            pauseInfo.x = stage.stageWidth;
            pauseInfo.y = stage.stageHeight;
            pauseInfo.addEventListener(MouseEvent.CLICK,pauseClick);
            addChild(pauseInfo);
        }

        private function keys(e:KeyboardEvent):void {
            trace("KeyboardEvent ",e);
            if (e.keyCode == 27) {  // esc key
                if (stage.contains(escapeKey)){
                    trace("remove escape");
                    escapeKey.visible = false;
                }
                else {
                    trace("show escape");
                    escapeKey.visible = true;
                }
            }
        }

        private function pauseClick(e:MouseEvent):void {
        //  The trace in 'keys' gives this:
        //[KeyboardEvent type="keyDown" bubbles=true cancelable=false eventPhase=2 charCode=27 keyCode=27 keyLocation=0 ctrlKey=false altKey=false shiftKey=false]      

            var a:KeyboardEvent = new KeyboardEvent("keyDown", true, false, 27, 27, 0, false, false, false);
            stage.dispatchEvent(a);
        }
    }
}

好的,现在我明白了。我只是不明白它的目的。我认为,代码中还有一个烦人的错误。

首先:您已经证明您基本上可以将一种类型的事件(例如 MouseEvent)“转换”为另一种类型的事件(KeyboardEvent)。但是您仍然为每个事件类型注册了一个侦听器函数(在某些时候,出于内存管理的目的,您必须将其删除)和一个新派发的事件,因此您并没有完全减少代码。这个技巧的价值到底是什么?为什么不只注册一个具有多种事件类型的监听器函数呢?在该函数中,您可以区分事件类型并相应地执行操作,例如使用如下一行:

     if(e.type == 'keyDown' || e.type == 'click')

第二:你说:if (stage.contains(escapeKey)) 然后你尝试使 escapeKey 的“可见”属性 依赖于那。但是通过设置 escapeKey.visible = false 你并没有改变舞台仍然包含 escapeKey 的事实。因此 escapeKey 将永远不会再次可见,因为 'else' 条件不存在。我相信您想说“removeChild(escapeKey)”然后是“addChild(escapeKey)”而不是设置“” escapeKey.visible = false”,然后是“escapeKey.visible = true”。然后你的小程序会做你想做的事。

+1 并大力支持@Neal Davis 的评论!

正如他所建议的,让一个监听两个事件的参数为 (e:Event) 是一种更清晰、更简单的实现相同结果的方法:

   pauseInfo.addEventListener(MouseEvent.CLICK,keys);
   stage.addEventListener(KeyboardEvent.KEY_DOWN, keys);

   private function keys(e:Event):void {
        trace("EscapeKey: ",e);   
        if (e.keyCode == 27) {
        ...    
        }
   }

尽管只有一个侦听器函数正在处理这两个侦听器,但在某些时候仍然必须删除两个侦听器!