Фокусирование клавиатуры в виджетах
Виджеты Qt обрабатывают фокус клавиатуры привычным для графических интерфейсов способом.
Основная проблема заключается в том, что нажатия клавиш пользователя могут быть направлены на любое из нескольких окон на экране и любые из нескольких виджетов внутри целевого окна. Когда пользователь нажимает клавишу, он ожидает, что она будет обработана в нужном месте, и программное обеспечение должно попытаться оправдать это ожидание. Система должна определить, к какому приложению направлено нажатие клавиши, к какому окну внутри этого приложения и к какому виджету внутри этого окна.
Движение фокуса
Принятые обычаи для перенаправления фокуса клавиатуры на определенный виджет таковы:
- Пользователь нажимает клавишу Tab (или Shift+Tab).
- Пользователь нажимает на виджет.
- Пользователь нажимает сочетание клавиш.
- Пользователь использует колесо мыши.
- Пользователь перемещает фокус в окно, и приложение должно определить, какой виджет внутри окна должен получить фокус.
Каждый из этих механизмов перемещения отличается, и разные типы виджетов получают фокус только в некоторых из них. Мы рассмотрим каждый из них по очереди.
Нажатие клавиш Tab или Shift+Tab
Нажатие клавиши Tab является наиболее распространенным способом перемещения фокуса с помощью клавиатуры. (Иногда в приложениях для ввода данных Enter выполняет ту же функцию, что и Tab; это легко реализуется в Qt с помощью фильтра событий event filter.)
Нажатие клавиши Tab во всех широко используемых сегодня системах окон переводит фокус клавиатуры на следующий виджет в циклическом списке внутри окна. Tab перемещает фокус по циклическому списку в одном направлении, Shift+Tab — в другом. Порядок, в котором нажатия клавиши Tab перемещают фокус с виджета на виджет, называется порядком табуляции.
Вы можете настроить порядок табуляции с помощью QWidget::setTabOrder(). (Если этого не сделать, Tab, как правило, перемещает фокус в порядке создания виджетов.) Qt Designer предоставляет средства визуального изменения порядка табуляции.
Поскольку нажатие клавиши Tab очень распространено, большинство виджетов, которые могут получить фокус, должны поддерживать фокус табуляции. Основное исключение — это редко используемые виджеты, для которых есть сочетания клавиш или обработчики ошибок, перемещающие фокус.
Например, в диалоговом окне ввода данных может быть поле, необходимое только в одном проценте случаев. В таком диалоговом окне Tab может пропустить это поле, и диалоговое окно может использовать один из этих механизмов:
- Если программа может определить, нужно ли это поле, она может переместить фокус туда, когда пользователь закончит ввод и нажмёт ОК или когда пользователь нажмёт Enter после заполнения других полей. В качестве альтернативы, включите поле в порядок табуляции, но отключите его. Включите его, если это станет уместно в свете того, что пользователь установил в других полях.
- Метка поля может содержать сочетание клавиш, которое переводит фокус в это поле.
Еще одно исключение из поддержки Tab — это виджеты для ввода текста, которые должны поддерживать вставку табуляций; практически все текстовые редакторы попадают в эту категорию. Qt обрабатывает Ctrl+Tab как Tab и Ctrl+Shift+Tab как Shift+Tab, и такие виджеты могут переопределить QWidget::event() и обработать Tab перед вызовом QWidget::event() для получения обычной обработки всех других клавиш. Однако, поскольку некоторые системы используют Ctrl+Tab для других целей, и многие пользователи об этом не знают, это не является полным решением.
Пользователь нажимает на виджет
Это, пожалуй, еще более распространено, чем нажатие клавиши Tab на компьютерах с мышью или другим указательным устройством.
Нажатие для перемещения фокуса немного мощнее, чем Tab. Хотя оно перемещает фокус на виджет, для виджетов-редакторов оно также перемещает курсор текста (внутренний фокус виджета) в место, где нажимается мышью.
Поскольку это так распространено и люди к этому привыкли, неплохо поддерживать его для большинства виджетов. Однако есть и важная причина, по которой следует этого избегать: вы можете не захотеть убирать фокус с виджета, где он был.
Например, в текстовом процессоре, когда пользователь нажимает на инструмент «Жирный» (B), что должно произойти с фокусом клавиатуры? Должен ли он остаться там, где он был, почти наверняка в виджете редактирования, или он должен перейти на кнопку «B»?
Мы рекомендуем поддерживать фокус при щелчке для виджетов, которые поддерживают ввод текста, и избегать его для большинства виджетов, где щелчок мышью имеет другой эффект. (Для кнопок мы также рекомендуем добавить сочетание клавиш: QAbstractButton и его подклассы делают это очень легко.)
В Qt только функция QWidget::setFocusPolicy() влияет на фокус при щелчке.
Пользователь нажимает сочетание клавиш
Необычным явлением является перемещение фокуса сочетанием клавиш. Это может произойти неявно при открытии модальных диалоговых окон, а также явно с помощью акселеров фокуса, таких как те, которые предоставляются QLabel::setBuddy(), QGroupBox и QTabBar.
Мы рекомендуем поддерживать фокус сочетания клавиш для всех виджетов, к которым пользователь может перейти. Например, диалоговое окно вкладок может иметь сочетания клавиш для каждой страницы, поэтому пользователь может нажать, например, Alt+P, чтобы перейти на страницу Pechat. Легко переборщить с этим: есть только несколько клавиш, и также важно предоставить сочетания клавиш для команд. 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/archives/qt-5.11/focus.html