• 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

  • 相关阅读:
    全卷积网络(FCN)与图像分割
    Mac下编译tesseract报错 DotProductAVX can't be used on Android
    OSTU二值化算法
    ssh的用户配置文件config管理ssh会话
    SSD: Single Shot MultiBox Detector 编译方法总结
    论文笔记——A Deep Neural Network Compression Pipeline: Pruning, Quantization, Huffman Encoding
    LeetCode——Word Break
    C#多线程编程
    impinj 编程接口
    C# 委托实例(跨窗体操作控件)
  • 原文地址:https://www.cnblogs.com/findumars/p/7952843.html
Copyright © 2020-2023  润新知