Фокусировка клавиатуры в виджетах
Виджеты Qt обрабатывают фокусировку клавиатуры так, как это стало обычной практикой в графических интерфейсах.
Основная проблема заключается в том, что нажатия клавиш пользователя могут быть направлены на любое из нескольких окон на экране и на любой из нескольких виджетов внутри целевого окна. Когда пользователь нажимает клавишу, он ожидает, что она попадет в нужное место, и программное обеспечение должно попытаться удовлетворить это ожидание. Система должна определить, к какому приложению направлено нажатие клавиши, к какому окну в этом приложении и к какому виджету в этом окне.
Движение фокуса
Принятые правила для перевода фокуса клавиатуры на определенный виджет таковы:
- Пользователь нажимает Tab (или Shift+Tab).
- Пользователь щелкает виджет.
- Пользователь нажимает сочетание клавиш.
- Пользователь использует колесо мыши.
- Пользователь перемещает фокус в окно, и приложение должно определить, какой виджет внутри окна должен получить фокус.
Каждый из этих механизмов движения различается, и разные типы виджетов получают фокус только при некоторых из них. Мы рассмотрим каждый из них по очереди.
Клавиша Tab или Shift+Tab
Нажатие клавиши Tab является, пожалуй, наиболее распространенным способом перемещения фокуса с помощью клавиатуры. (Иногда в приложениях для ввода данных клавиша Enter выполняет ту же функцию, что и Tab; это легко реализовать в Qt, реализовав фильтр событий.)
Нажатие клавиши 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 для других целей, а многие пользователи вообще не знают о 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-6.2/focus.html