Фокусировка клавиатуры в виджетах
Виджеты Qt обрабатывают фокус клавиатуры так, как это стало обычным в графических интерфейсах пользователя.
Основная проблема заключается в том, что нажатия клавиш пользователя могут быть направлены на любой из нескольких окон на экране, и на любой из нескольких виджетов внутри целевого окна. Когда пользователь нажимает клавишу, он ожидает, что она попадет в нужное место, и программное обеспечение должно постараться удовлетворить это ожидание. Система должна определить, к какому приложению направлено нажатие клавиши, к какому окну в рамках этого приложения и к какому виджету в этом окне.
Движение фокуса
Принятые правила для направления фокуса клавиатуры на конкретный виджет таковы:
- Пользователь нажимает клавишу Tab (или Shift+Tab).
- Пользователь щелкает по виджету.
- Пользователь нажимает сочетание клавиш.
- Пользователь использует колесо мыши.
- Пользователь перемещает фокус в окно, и приложение должно определить, какой виджет в окне должен получить фокус.
Каждый из этих механизмов перемещения отличается, и разные типы виджетов получают фокус только при некоторых из них. Мы рассмотрим каждый из них по очереди.
Клавиша Tab или Shift+Tab
Нажатие клавиши Tab является наиболее распространенным способом перемещения фокуса с помощью клавиатуры. (Иногда в приложениях для ввода данных клавиша Enter выполняет ту же функцию, что и Tab; это легко достигается в Qt путём реализации фильтра событий фильтра событий.)
Нажатие клавиши Tab во всех используемых сегодня оконных системах перемещает фокус клавиатуры на следующий виджет в циклическом списке внутри окна. Tab перемещает фокус по циклическому списку в одном направлении, а Shift+Tab — в другом. Порядок, в котором нажатия Tab перемещают фокус с одного виджета на другой, называется порядком ввода.
Вы можете настроить порядок ввода с помощью QWidget::setTabOrder(). (Если этого не сделать, Tab обычно перемещает фокус в порядке создания виджетов.) Qt Designer предоставляет средства для визуального изменения порядка ввода.
Поскольку нажатие клавиши Tab очень распространено, большинство виджетов, которые могут иметь фокус, должны поддерживать фокус от Tab. Главное исключение — это редко используемые виджеты, где существует какое-то сочетание клавиш или обработчик ошибок, перемещающий фокус.
Например, в диалоговом окне для ввода данных может быть поле, которое необходимо только в одном случае из ста. В таком диалоговом окне Tab может пропускать это поле, и диалоговое окно может использовать один из этих механизмов:
- Если программа может определить, нужно ли поле, она может переместить фокус туда, когда пользователь завершит ввод и нажмёт ОК, или когда пользователь нажмёт Enter после заполнения других полей. В качестве альтернативы, включите поле в порядок ввода, но отключите его. Включите его, если это станет уместно с учётом того, что пользователь ввёл в другие поля.
- Надпись к полю может содержать сочетание клавиш, перемещающее фокус в это поле.
Ещё одно исключение из поддержки Tab — это виджеты ввода текста, которые должны поддерживать вставку табуляции; почти все текстовые редакторы относятся к этому классу. Qt рассматривает Ctrl+Tab как Tab, а Ctrl+Shift+Tab как Shift+Tab, и такие виджеты могут переопределять QWidget::event() и обрабатывать Tab перед вызовом QWidget::event() для получения нормальной обработки всех остальных клавиш. Однако, поскольку некоторые системы используют Ctrl+Tab для других целей, и многие пользователи не знают о Ctrl+Tab, это не является полным решением.
Нажатие пользователем на виджет
Это, пожалуй, ещё более распространено, чем нажатие клавиши Tab на компьютерах с мышью или другим устройством указания.
Щелчок для перемещения фокуса немного мощнее, чем Tab. В то время как он перемещает фокус к виджету, для виджетов редактора он также перемещает курсор текста (внутренний фокус виджета) в точку, где щелкнул пользователь мышью.
Поскольку это так часто используется и люди привыкли к этому, рекомендуется поддерживать его для большинства виджетов. Однако существует и важная причина избегать этого: вы можете не захотеть снимать фокус с виджета, где он был.
Например, в текстовом процессоре, когда пользователь нажимает кнопку инструмента «Жирный» ('B'), что должно произойти с фокусом клавиатуры? Должен ли он остаться там, где был, практически наверняка в виджете редактирования, или он должен переместиться на кнопку «Жирный»?
Мы рекомендуем поддерживать фокусирование щелчком для виджетов, поддерживающих ввод текста, и избегать его для большинства виджетов, где щелчок мышью имеет другой эффект. (Для кнопок также рекомендуется добавить сочетание клавиш: QAbstractButton и его подклассы делают это очень легко.)
В Qt только функция QWidget::setFocusPolicy() влияет на фокусирование щелчком.
Нажатие пользователем сочетания клавиш
Не является редкостью, когда сочетания клавиш перемещают фокус. Это может происходить неявно при открытии модальных диалоговых окон, но также явно с использованием акселераторов фокуса, таких как те, которые предоставляются QLabel::setBuddy(), QGroupBox и QTabBar.
Мы рекомендуем поддерживать фокусирование по сочетанию клавиш для всех виджетов, к которым пользователь может захотеть перейти. Например, диалоговое окно вкладок может иметь сочетания клавиш для каждой из своих страниц, так что пользователь может нажать, например, Alt+P, чтобы перейти на страницу Pечать. Легко переусердствовать: клавиш всего несколько, и также важно предоставлять сочетания клавиш для команд. Alt+P также используется для вставки, воспроизведения, печати и печати здесь в списке Стандартных сочетаний клавиш, например.
Вращение пользователем колеса мыши
В Microsoft Windows использование колеса мыши всегда обрабатывается виджетом, имеющим фокус клавиатуры. В macOS и X11 — виджетом, получающим другие события мыши.
Способ, которым Qt обрабатывает это различие платформ, заключается в том, что виджеты перемещают фокус клавиатуры при использовании колеса. При правильной политике фокусировки каждого виджета приложения могут работать корректно в Windows, macOS и X11.
Перемещение фокуса пользователем в это окно
В этой ситуации приложение должно определить, какой виджет в окне должен получить фокус.
Это может быть просто: если фокус был в этом окне раньше, то последний виджет, имевший фокус, должен его вернуть. Qt делает это автоматически.
Если фокус никогда не был в этом окне, и вы знаете, где фокус должен начаться, вызовите QWidget::setFocus() для виджета, который должен получить фокус, перед вызовом QWidget::show() для него. Если вы этого не сделаете, Qt выберет подходящий виджет.
© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-5.15/focus.html