们日常切换控件,例如QQ登陆的账号和密码输入框就可以通过Tab键切换焦点。
图1 qq切换焦点
Qt中QWidget提供了一个静态方式实现该效果
其中也包含介绍使用
[static] void QWidget::setTabOrder(QWidget *first, QWidget *second)
Puts the second widget after the first widget in the focus order. Note that since the tab order of the second widget is changed, you should order a chain like this: setTabOrder(a, b); // a to b setTabOrder(b, c); // a to b to c setTabOrder(c, d); // a to b to c to d not like this: // WRONG setTabOrder(c, d); // c to d setTabOrder(a, b); // a to b AND c to d setTabOrder(b, c); // a to b to c, but not c to d If first or second has a focus proxy, setTabOrder() correctly substitutes the proxy.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
实现效果如下
图2 Tab切换焦点
主要部分源码
QPushButton *p = new QPushButton("按钮"); QLineEdit *l = new QLineEdit("输入框"); QCheckBox *c = new QCheckBox("复选框"); QComboBox *b = new QComboBox; setTabOrder(p, l); setTabOrder(l, c); setTabOrder(c, b);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
当然也可以让控件屏蔽焦点的使用,或者接受响应其他类型的焦点方式
主要使用
void setFocusPolicy(Qt::FocusPolicy policy)
- 1
其中Qt::FocusPolicy 这个枚举类型定义了一个控件可以用来获取键盘焦点的各种策略。
Constant | Value | Description |
---|---|---|
Qt::TabFocus | 0x1 | the widget accepts focus by tabbing. |
Qt::ClickFocus | 0x2 | the widget accepts focus by clicking. |
Qt::StrongFocus | TabFocus | ClickFocus | 0x8 | he widget accepts focus by both tabbing and clicking. On macOS this will also be indicate that the widget accepts tab focus when in ‘Text/List focus mode’. |
Qt::WheelFocus | StrongFocus | 0x4 | like Qt::StrongFocus plus the widget accepts focus by using the mouse wheel. |
Qt::NoFocus | 0 | the widget does not accept focus. |
例如设置
QCheckBox为NoFouse
c->setFocusPolicy(Qt::NoFocus);
- 1
效果如下
图3 复选框设置NoFocuse
函数
[slot] void QWidget::setFocus() //可通过信号槽方式设置 This is an overloaded function. Gives the keyboard input focus to this widget (or its focus proxy) if this widget or one of its parents is the active window.
- 1
- 2
- 3
可直接设置焦点
接下来可以看一下Qt是怎么实现焦点切换的,查看qwidget.cpp源码
void QWidget::setTabOrder(QWidget* first, QWidget *second) { //如果这两个控件都设置为没有焦点则不进行焦点设置,如图3中所示 if (!first || !second || first->focusPolicy() == Qt::NoFocus || second->focusPolicy() == Qt::NoFocus) return; /****************************************************************** QWidget *QWidget::window() const { QWidget *w = const_cast<QWidget *>(this); QWidget *p = w->parentWidget(); while (!w->isWindow() && p) { w = p; p = p->parentWidget(); } return w; } ******************************************************************/ //查看当前控件“祖先”(ancestor widget)窗口,见上面代码 if (Q_UNLIKELY(first->window() != second->window())) { qWarning("QWidget::setTabOrder: 'first' and 'second' must be in the same window"); return; } //找到first或其子类中焦点的控件(不是很懂) QWidget *fp = first->focusProxy(); if (fp) { QList<QWidget *> l = first->findChildren<QWidget *>(); for (int i = l.size()-1; i >= 0; --i) { QWidget * next = l.at(i); if (next->window() == fp->window()) { fp = next; if (fp->focusPolicy() != Qt::NoFocus) break; } } first = fp; } if (fp == second) return; if (QWidget *sp = second->focusProxy()) second = sp; //双向链表存储焦点触发控件顺序 // QWidget *fp = first->d_func()->focus_prev; QWidget *fn = first->d_func()->focus_next; if (fn == second || first == second) return; QWidget *sp = second->d_func()->focus_prev; QWidget *sn = second->d_func()->focus_next; fn->d_func()->focus_prev = second; first->d_func()->focus_next = second; second->d_func()->focus_next = fn; second->d_func()->focus_prev = first; sp->d_func()->focus_next = sn; sn->d_func()->focus_prev = sp; //查错 Q_ASSERT(first->d_func()->focus_next->d_func()->focus_prev == first); Q_ASSERT(first->d_func()->focus_prev->d_func()->focus_next == first); Q_ASSERT(second->d_func()->focus_next->d_func()->focus_prev == second); Q_ASSERT(second->d_func()->focus_prev->d_func()->focus_next == second); }
http://blog.csdn.net/gx864102252/article/details/72731992