Qt源码分析--QWidget(7)--Keyboard focus functions

Qt框架中的焦点管理与键盘导航实现解析
本文详细介绍了Qt框架中关于焦点管理的几个关键函数:setFocus()用于设置焦点,clearFocus()清除焦点,setTabOrder()设置焦点顺序,setFocusProxy()指定焦点代理,以及focusNextChild()和focusPreviousChild()切换焦点。这些函数协同工作,确保了Qt应用程序中控件的焦点流动和键盘导航的正确性。

1.void setFocus()

inline void setFocus() { setFocus(Qt::OtherFocusReason); }

void QWidget::setFocus(Qt::FocusReason reason)
{
    if (!isEnabled())
        return;
    QWidget *f = d_func()->deepestFocusProxy();
    if (!f)
        f = this;
    if (QApplication::focusWidget() == f)
        return;
#if QT_CONFIG(graphicsview)
    QWidget *previousProxyFocus = nullptr;
    if (const auto &topData = window()->d_func()->extra) {
        if (topData->proxyWidget && topData->proxyWidget->hasFocus()) {
            previousProxyFocus = topData->proxyWidget->widget()->focusWidget();
            if (previousProxyFocus && previousProxyFocus->focusProxy())
                previousProxyFocus = previousProxyFocus->focusProxy();
            if (previousProxyFocus == f && !topData->proxyWidget->d_func()->proxyIsGivingFocus)
                return;
        }
    }
#endif
#if QT_CONFIG(graphicsview)
    // Update proxy state
    if (const auto &topData = window()->d_func()->extra) {
        if (topData->proxyWidget && !topData->proxyWidget->hasFocus()) {
            f->d_func()->updateFocusChild();
            topData->proxyWidget->d_func()->focusFromWidgetToProxy = 1;
            topData->proxyWidget->setFocus(reason);
            topData->proxyWidget->d_func()->focusFromWidgetToProxy = 0;
        }
    }
#endif
    if (f->isActiveWindow()) {
        QWidget *prev = QApplicationPrivate::focus_widget;
        if (prev) {
            if (reason != Qt::PopupFocusReason && reason != Qt::MenuBarFocusReason
                && prev->testAttribute(Qt::WA_InputMethodEnabled)) {
                QGuiApplication::inputMethod()->commit();
            }
            if (reason != Qt::NoFocusReason) {
                QFocusEvent focusAboutToChange(QEvent::FocusAboutToChange, reason);
                QCoreApplication::sendEvent(prev, &focusAboutToChange);
            }
        }
        f->d_func()->updateFocusChild();
        QApplicationPrivate::setFocusWidget(f, reason);
#ifndef QT_NO_ACCESSIBILITY
        // menus update the focus manually and this would create bogus events
        if (!(f->inherits("QMenuBar") || f->inherits("QMenu") || f->inherits("QMenuItem")))
        {
            QAccessibleEvent event(f, QAccessible::Focus);
            QAccessible::updateAccessibility(&event);
        }
#endif
#if QT_CONFIG(graphicsview)
        if (const auto &topData = window()->d_func()->extra) {
            if (topData->proxyWidget) {
                if (previousProxyFocus && previousProxyFocus != f) {
                    // Send event to self
                    QFocusEvent event(QEvent::FocusOut, reason);
                    QPointer<QWidget> that = previousProxyFocus;
                    QCoreApplication::sendEvent(previousProxyFocus, &event);
                    if (that)
                        QCoreApplication::sendEvent(that->s
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天天进步2015

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值