Использование клавиши со стрелкой в ​​качестве эквивалента клавиши с NSMenuItem

У меня возникают некоторые проблемы с обработкой событий при попытке использовать клавиши со стрелками без модификаторов в качестве эквивалентов клавиш для пунктов меню в строке главного меню. Проблема, с которой я сталкиваюсь, заключается в том, что строка главного меню обрабатывает событие нажатия клавиши как событие, эквивалентное клавише, до того, как tableView сможет это сделать. Когда tableView является первым ответчиком, клавиши со стрелками вверх/вниз не изменяют выбор tableView, а вызывают эквивалент клавиши в строке главного меню.

Причина этого в том, что входящее событие keyDown для клавиши со стрелкой сначала передается performKeyEquivalent в целевом окне, которое, в свою очередь, передает это событие вниз по цепочке. NSTableView не отвечает на это, поэтому событие всплывает обратно в приложение, где оно затем отправляет его в главное меню через performKeyEquivalent, и, таким образом, событие потребляется.

Если в главном меню нет эквивалента клавиши, то событие возвращается к окну и далее по цепочке через keyDown, на что tableView действительно реагирует и корректно обрабатывает.

Это задокументировано Apple (более или менее) в их Руководство по обработке событий.

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

Я пробовал разные трюки, но каждый из них имеет множество плюсов и минусов:

Делегат NSMenu

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

Подкласс NSApplication

Вы можете переопределить sendEvent: в NSApplication, но логика отслеживания того, где вы находитесь в цепочке обработки событий, становится немного запутанной.

Нажатие NSEvent

Подобно подклассу NSApplication. Здесь все немного чище, потому что я могу обмануть и сделать касание события немного ближе к tableView, но у вас все еще остается много логики, чтобы определить, когда касание должно потреблять событие и «принудительно передавать» его в tableView по сравнению с тем, когда вы должны разрешить обработку события в обычном режиме.

Мне любопытно, есть ли у кого-нибудь предложения о том, как лучше всего реализовать клавишу со стрелкой в ​​​​качестве эквивалента клавиши, когда модификаторы отсутствуют и может присутствовать tableView.

(макОС 10.11+)


person kennyc    schedule 09.09.2016    source источник
comment
Я столкнулся с той же проблемой. Вы можете взглянуть на stackoverflow.com/q/61839795/3272409, где более подробно обсуждается эта проблема. Решение, которое я выбрал, заключалось в том, чтобы не использовать эквиваленты клавиш, а зарегистрировать клавиши со стрелками в методе keyDown(with:). Это решило проблему для меня.   -  person Codey    schedule 19.05.2020