部件中的键盘焦点
Qt Widgets 处理键盘焦点的方式已成为图形用户界面的惯例。
基本的问题是,用户的按键可以指向屏幕上多个窗口中的任意一个,以及目标窗口中多个部件中的任意一个。当用户按下一个键时,他们希望它能按到正确的位置,而软件必须尽力满足这一期望。系统必须确定按键指向哪个应用程序、该应用程序中的哪个窗口以及该窗口中的哪个部件。
焦点移动
将键盘焦点指向特定部件的习惯做法有以下几种:
- 用户按Tab (或Shift+Tab )。
- 用户点击部件。
- 用户按下键盘快捷键。
- 用户使用鼠标滚轮。
- 用户将焦点移至窗口,应用程序必须确定窗口中的哪个部件应获得焦点。
这些移动机制各有不同,不同类型的部件只能在其中某些机制中获得焦点。下面我们将逐一介绍。
Tab 或 Shift+Tab
到目前为止,按Tab 是使用键盘移动焦点的最常见方式。(有时在数据录入应用程序中,回车键的作用与Tab 相同;在 Qt XML 中,通过实现事件过滤器就能轻松实现这一功能)。
在目前常用的所有窗口系统中,按下Tab 会将键盘焦点移动到每个窗口循环列表中的下一个部件。Tab 会沿循环列表的一个方向移动焦点,Shift+Tab 则沿另一个方向移动焦点。Tab 在窗口部件之间移动的顺序称为制表符顺序。
您可以使用QWidget::setTabOrder() 自定义选项卡顺序。(如果不这样做,Tab 通常会按照窗口小部件的构建顺序移动焦点。)Qt Widgets Designer 提供了一种可视化更改选项卡顺序的方法。
由于按Tab 是非常常见的操作,因此大多数可以获得焦点的部件都应支持标签页焦点。主要的例外是很少使用的部件,以及有键盘加速器或错误处理程序来移动焦点的部件。
例如,在数据输入对话框中,可能有一个字段只有在百分之一的情况下才需要使用。在这样的对话框中,Tab 可以跳过这个字段,对话框也可以使用上述机制之一:
- 如果程序可以确定是否需要该字段,则可以在用户完成输入并按下OK 时,或在用户完成其他字段后按下回车键时,将焦点移至该字段。或者,在制表符顺序中包含该字段,但将其禁用。如果考虑到用户在其他字段中的设置,可以启用该字段。
- 字段的标签可以包含将焦点移至该字段的键盘快捷键。
Tab 支持的另一个例外是必须支持插入制表符的文本输入部件;几乎所有文本编辑器都属于这一类。Qt 将Ctrl+Tab 视为Tab ,将Ctrl+Shift+Tab 视为Shift+Tab ,此类部件可以重新实现QWidget::event() 并在调用QWidget::event() 之前处理 Tab,以获得对所有其他按键的正常处理。不过,由于有些系统将Ctrl+Tab 用于其他目的,而且许多用户并不知道Ctrl+Tab ,因此这并不是一个完整的解决方案。
用户点击小工具
在使用鼠标或其他指向设备的电脑上,这可能比按Tab 更常见。
单击移动焦点的功能比Tab 稍强。单击移动焦点可以将焦点移到部件上,对于编辑器部件来说,它还可以将文本光标(部件的内部焦点)移到单击鼠标的位置。
由于它非常常见,而且人们已经习惯使用它,因此大多数部件都支持它是个好主意。不过,也有一个重要的原因需要避免:你可能不想从原来的部件上移除焦点。
例如,在文字处理器中,当用户点击 "B"(粗体)工具按钮时,键盘焦点会发生什么变化?是继续留在原来的位置(几乎肯定是在编辑部件中),还是移动到 "B "按钮上?
我们建议支持文本输入的 widget 支持点击对焦,而对于鼠标点击会产生不同效果的大多数 widget,则应避免点击对焦。(对于按钮,我们还建议添加键盘快捷方式:QAbstractButton 及其子类可以轻松实现这一点)。
在 Qt XML 中,只有QWidget::setFocusPolicy() 函数会影响点击焦点。
用户按下键盘快捷键
键盘快捷键移动焦点的情况并不少见。这种情况可能通过打开模式对话框隐式地发生,也可能通过使用焦点加速器显式地发生,如QLabel::setBuddy() 、QGroupBox 和QTabBar 所提供的加速器。
您的应用程序可以为用户希望跳转到的所有部件支持快捷键焦点。例如,标签对话框的每个页面都可以使用键盘快捷键,因此用户可以按Alt+P 等键跳转到打印页面。请注意,由于只有几个按键,这样做很容易过度,而且为命令提供键盘快捷方式也很重要。请参考目标平台的设计指南,例如微软的键盘用户界面设计指南或苹果的焦点和选择指南。
用户旋转鼠标滚轮
在 Microsoft Windows 上,鼠标滚轮的使用总是由键盘焦点所在的部件处理。而在 macOS 和 X11 上,则由获得其他鼠标事件的部件处理。
Qt 处理这一平台差异的方法是,在使用滚轮时让部件移动键盘焦点。只要在每个部件上采用正确的焦点策略,应用程序就能在 Windows、macOS 和 X11 上正常工作。
用户将焦点移至该窗口
在这种情况下,应用程序必须确定窗口中的哪个部件应获得焦点。
这可以很简单:如果焦点曾在此窗口中出现过,那么最后一个获得焦点的部件应重新获得焦点。Qt 会自动这样做。
如果焦点以前从未在此窗口中出现过,而且您知道焦点应该从哪里开始,那么在调用QWidget::show() 之前,请在应该接收焦点的部件上调用QWidget::setFocus() 。如果不这样做,Qt 会选择一个合适的部件。
© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.