Qt控件焦点切换

时间:2017-12-02 10:52:06   收藏:0   阅读:914

们日常切换控件,例如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切换焦点 
主要部分源码

    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);

当然也可以让控件屏蔽焦点的使用,或者接受响应其他类型的焦点方式 
主要使用

void setFocusPolicy(Qt::FocusPolicy policy)

其中Qt::FocusPolicy 这个枚举类型定义了一个控件可以用来获取键盘焦点的各种策略。

ConstantValueDescription
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);

效果如下 
技术分享图片 
图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.

可直接设置焦点

接下来可以看一下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

 

原文:http://www.cnblogs.com/findumars/p/7952843.html

评论(0
© 2014 bubuko.com 版权所有 - 联系我们:wmxa8@hotmail.com
打开技术之扣,分享程序人生!