們平常切換控件,例如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.
實現效果以下
圖2 Tab切換焦點
主要部分源碼ui
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);
固然也能夠讓控件屏蔽焦點的使用,或者接受響應其餘類型的焦點方式
主要使用this
void setFocusPolicy(Qt::FocusPolicy policy)
其中Qt::FocusPolicy 這個枚舉類型定義了一個控件能夠用來獲取鍵盤焦點的各類策略。spa
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.net
c->setFocusPolicy(Qt::NoFocus);
效果以下
圖3 複選框設置NoFocuse
函數code
[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.
可直接設置焦點regexp
接下來能夠看一下Qt是怎麼實現焦點切換的,查看qwidget.cpp源碼blog
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/72731992coffeescript