不是所有的窗口都可以成为焦点窗口,只有“可获取焦点”的窗口,才有机会成为焦点窗口,Qt提供了如下接口,用于设置窗口是否是”可获取焦点“窗口:
void QWidget::setFocusPolicy(Qt::FocusPolicy policy);
Qt::FocusPolicy值 | 描述 |
---|---|
Qt::TabFocus | 与焦点链相关,详解见下一小节 |
Qt::ClickFocus | 单击该窗口,获得焦点 |
Qt::StrongFocus | TabFocus | ClickFocus | 0x8 |
Qt::WheelFocus | StrongFocus | 0x4 |
Qt::NoFocus | 不可获取焦点 |
setFocusPolicy()
的参数值可以是上述5个值中的任意一种,当参数值为前4个的时候,当前窗口可以获取焦点,当参数值为Qt::Nofocus
的时候,当前窗口不可获取焦点。
2.焦点链
Qt除了把窗口对象组织成树状结构外,还把这些窗口组织成了一个双向链表结构,这个链表叫做焦点链。焦点链上每个节点代表一个窗口,默认情况下,窗口在焦点链上的先后位置,与用户把窗口添加到窗口树的先后顺序有关,越早添加到窗口树上的窗口,其在焦点链中的位置越靠前。
通过按Tab
或者Shift+Tab
,可以实现焦点在各个窗口之间循环移动。焦点移动顺序与焦点链相关,它的移动规律如下:
1.点击Tab
键,焦点链指针向后移动,直至碰到第一个FocusPolicy
为TabFocus
的窗口,并设置该窗口为焦点窗口;
2.点击Shift+Tab
,焦点链指针向前移动,直至碰到第一个FocusPolicy
为TabFocus
的窗口,并设置该窗口为焦点窗口;
Qt提供了下列结构,用于获取焦点链信息:
//返回此部件焦点链中的下一个部件
QWidget* QWidget::nextInFocusChain() const;
//返回此部件焦点链中的前一个部件
QWidget* QWidget::previousInFocusChain() const;
此外,我们还可以调整焦点链中节点的先后顺序
// 将焦点顺序中的部件 second 放置在部件 first 之后
static void QWidget::setTabOrder(QWidget* first, QWidget* second);
比如,若默认的焦点链顺序为 a-b-c-d,则:
setTabOrder(d,c); //改变后焦点链的顺序为 a-b-d-c
setTabOrder(b,a); //改变后焦点链的顺序为 b-a-d-c
3.切换焦点窗口
下面这些API可以用于切换焦点窗口:
// 等同于focusNextPrevChild(true)
bool QWidget::focusNextChild();
// 等同于focusNextPrevChild(false)
bool QWidget::focusPreviousChild();
// next==true:设置焦点链中下个`FocusPolicy`为`TabFocus`的窗口为焦点窗口
// next==false:设置焦点链中前一个`FocusPolicy`为`TabFocus`的窗口为焦点窗口
bool QWidget::focusNextPrevChild(bool next);
// 设置当前窗口为焦点窗口
void QWidget::setFocus(Qt::FocusReason reason);
// 取消焦点窗口
void QWidget::clearFocus();
点击Tab
键,底层调用了focusNextChild()
,点击Shift+Tab
,底层调用了focusPreviousChild()
。
setFocus(Qt::FocusReason reason)
有两个作用:设置当前窗口为焦点窗口;提供FocusReason
信息。
4.焦点事件
与焦点事件处理相关的函数如下:
void QWidget::focusInEvent(QFocusEvent *event);
void QWidget::focusOutEvent(QFocusEvent *event);
当焦点从一个部件移动到另一个部件时,会触发QFocusEvent
事件,这个事件会被发送给原焦点窗口和当前焦点窗口,原焦点窗口执行focusOutEvent()
,新焦点窗口执行focusInEvent()
。
5.焦点代理
顾名思义,就是代为接收焦点事件。比如,控件B是控件A的焦点代理,则当控件A获得焦点时,实际获得并处理焦点的是控件B。涉及到的接口:
//返回该窗口的焦点代理
QWidget* QWidget::focusProxy() const;
//设置该窗口的焦点代理为w
void QWidget::setFocusProxy(QWidget* w);
6.自定义焦点链
重载实现下列函数,可用于自定义焦点链。
bool QWidget::focusNextPrevChild(bool next);