События клавиатуры AS3 не запускаются до тех пор, пока я не нажму на экранную кнопку

#flash #actionscript-3

#flash #actionscript-3

Вопрос:

Итак, вот моя настройка:

Мой класс документа Main.as (это расширяет MovieClip). Следующий код находится в моем Main.as.

Я объявил все эти переменные в своем определении класса:

 private var holder:MovieClip;
private var leftButton:SimpleButton;
private var rightButton:SimpleButton;
  

в конструкторе…

 holder = new MovieClip();
addChild(holder);
holder.addEventListener(KeyboardEvent.KEY_UP, handleKeyboardEvent);

leftButton = new Arrow();
rightButton = new Arrow();

holder.addChild(leftButton);
holder.addChild(rightButton);

leftButton.x = 50;
leftButton.rotation = 180;
rightButton.x = 150;

leftButton.y = rightButton.y = 50;

leftButton.addEventListener(MouseEvent.CLICK, handlePaging);
rightButton.addEventListener(MouseEvent.CLICK, handlePaging);
  

… вне конструктора…

 public function handleKeyboardEvent ( e:KeyboardEvent ) {
            trace("got a keyboard event");

                trace("e.charCode : "   e.charCode);
                trace("e.keyCode : "   e.keyCode);
                switch (e.keyCode) {
                    case 37: //left arrow
                        showPreviousMoment();
                        break;
                    case 39: //right arrow
                        showNextMoment();
                        break;
                }


        }
  

Эти две кнопки являются экземплярами видеоролика со стрелкой, который у меня есть в библиотеке. Видеоролик со стрелкой содержит только графику (в диалоговом окне свойств для него базовым классом является flash.display.SimpleButton).

Я хочу, чтобы пользователь мог нажимать экранные стрелки или клавиши со стрелками на клавиатуре, чтобы перелистывать страницу вперед и назад.

Итак … когда я тестирую фильм или публикую его как приложение, нажатие левой и правой клавиш клавиатуры ничего не делает. ОДНАКО…ПОСЛЕ того, как я нажму на экранные стрелки, ТОГДА события клавиатуры будут обнаружены!!! Почему мои события клавиатуры не принимаются изначально? Почему при нажатии на экранные кнопки «держатель» начинает получать события?

Обновить

Я также только что закомментировал весь свой код, ЗА исключением создания экземпляра ‘holder’ и добавления прослушивателя. События клавиатуры не прослушиваются владельцем.

Обновить…ОТВЕТИТЬ

Итак, я выяснил, что если я хочу глобально прослушать KeyboardEvent, я должен зарегистрировать stage в качестве слушателя. Итак, это сделало свое дело:

 stage.addEventListener(KeyboardEvent.KEY_UP, handleKeyboardEvent);
  

Информация из книги Колина Мука:

События ввода с клавиатуры, которые запускают команды всего приложения, обычно обрабатываются глобально слушателями, зарегистрированными в экземпляре Stage Flash Player. Напротив, события ввода с клавиатуры, которые запускают определенный ответ элемента интерфейса, обычно обрабатываются слушателями, зарегистрированными в объекте, который в данный момент находится в фокусе клавиатуры.

Итак, я предполагаю, что в моей первоначальной версии, когда я нажимал на экранную кнопку со стрелкой, я каким-то образом фокусировал клавиатуру на ‘holder;.

Комментарии:

1. Вы уверены, что события клавиатуры запускаются при нажатии на стрелки, а не просто при нажатии на что-либо во флэш-ролике? Потому что, похоже, вам нужно сфокусировать окно flash, чтобы события клавиатуры работали. Попробуйте нажать на что-нибудь другое во флэш-ролике (не на стрелки), а затем протестируйте нажатие стрелок на клавиатуре, если это сработает, это означает, что с вашим кодом все в порядке, и все работает так, как должно.

2. Я забыл упомянуть, что это не проблема с фокусом. Я нажимал на разные части окна фильма, и это не «активировало» клавиши. Это происходит только после того, как я нажимаю на экранные кнопки… затем клавиши активны.

3. Не могли бы вы добавить функцию подкачки к вопросу? возможно, там есть что-то, что активирует события клавиатуры. (просто дикое предположение)

4. Я знал, что это как-то связано с фокусом. Возможно, фокус не на окне flash, а на держателе mc. =D И поскольку стрелки находятся внутри держателя, технически вы щелкаете по держателю, когда нажимаете стрелки, фокусируясь на соответствующем mc.

5. Опубликуйте ответ самостоятельно, и отметка принята, вы поняли это законно, и если проблема решена, то вопрос должен показать, что на него был дан ответ. 🙂

Ответ №1:

Обычно объект, на который вы нажимаете, попадает в фокус. Это действительно влияет на слушателей, вот почему это работает, когда вы добавляете его на сцену.

Когда вы нажимали на любой из них, ваш объект «holder» попадал в фокус, поэтому событие запускалось. Теперь вы делаете это хорошо, что добавили это на сцену.

Комментарии:

1. Два основных свойства определяют, вызывает ли взаимодействие изменения фокуса. mouseEnabled (при значении false) останавливает события мыши и клавиатуры. Предполагая, что mouseEnabled имеет значение true, любому подклассу InteractiveObject (текстовые поля, спрайты, видеоролики и т.д.) Можно вручную назначить фокус с помощью stage. свойство фокусировки. ОДНАКО по умолчанию объекты (за исключением текстового поля и SimpleButton) не будут автоматически попадать в фокус при нажатии, если для параметра «tabEnabled» не установлено значение true. Когда buttonMode имеет значение true, tabEnabled становится true. Таким образом, значение tabEnabled определяет, может ли щелчок или вкладка привести к фокусировке объекта.

Ответ №2:

Более динамичным решением (скажем, если вы динамически создаете экземпляр класса, который содержит movieclip) является использование:

 stage.focus = this;
  

Итак, если вы примените прослушиватель событий к экземпляру класса, которому действительно необходимо прослушивать ключевые события, это может сработать лучше для вас.

Для меня предыдущие предложения не сработали, поскольку я добавлял экземпляр моего основного класса во время выполнения. В итоге мой код выглядел следующим образом:

 Main.singletron.stage.addEventListener(KeyboardEvent.KEY_UP, checkKeyDown);
Main.singletron.stage.focus = this;
  

… вам нужно будет настроить синглетрон для работы этих двух строк.

Комментарии:

1. синглетрон, лол. это должно быть одноэлементным en.wikipedia.org/wiki/Singleton_pattern

Ответ №3:

Я публикую ответ на свой собственный вопрос, основанный на рекомендации @Ascension Systems. Я просто копирую из своего обновления на свой вопрос выше.

Обновить…ОТВЕТИТЬ

Итак, я выяснил, что если я хочу глобально прослушать KeyboardEvent, я должен зарегистрировать stage в качестве слушателя. Итак, это сделало свое дело:

 stage.addEventListener(KeyboardEvent.KEY_UP, handleKeyboardEvent);
  

Информация из книги Колина Мука:

События ввода с клавиатуры, которые запускают команды всего приложения, обычно обрабатываются глобально слушателями, зарегистрированными в экземпляре Stage Flash Player. Напротив, события ввода с клавиатуры, которые запускают определенный ответ элемента интерфейса, обычно обрабатываются слушателями, зарегистрированными в объекте, который в данный момент находится в фокусе клавиатуры.

Итак, я предполагаю, что в моей первоначальной версии, когда я нажимал на экранную кнопку со стрелкой, я каким-то образом фокусировал клавиатуру на «держателе».