zoukankan      html  css  js  c++  java
  • Qt控件焦点切换

    们日常切换控件,例如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 这个枚举类型定义了一个控件可以用来获取键盘焦点的各种策略。

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

  • 相关阅读:
    Linux 如何查看当前目录
    Docker快速入手实战笔记
    【ssh】ssh登录出现‘The authenticity of host ‘IP’ can't be established.’的问题
    【AFL(七)】afl-fuzz.c小改——输出文件夹暂存
    【steam】Steam背景美化——长展柜终极指南
    【AFL(六)】AFL源码中的那些头文件
    【AFL(五)】文件变异策略
    【Latex】详细的简易教程——写在论文开始之前
    【Latex】论文写作工具:VScode 2019 + latex workshop
    【AFL(四)】afl-cmin修改:文件夹相关操作鲁棒性
  • 原文地址:https://www.cnblogs.com/findumars/p/7952843.html
Copyright © 2011-2022 走看看