Qt qwidget 源码剖析 (一)

前言:

今天看了看 qt qwidget的源码 ,看不不是很细 粗略的看一下 类的结构,构造 和 一些函数
这里把怎么查看源码,查看源码的流程 的方法给大家分享一下(最后我也没找到调用 Win32API 的地方 ε=(´ο`*)))唉)

首先 你要确认在装Qt 时 勾选了 Source 模块 ,里面就是源码

在这里插入图片描述

然后在 调试器里面 配置源码的路径
路径就是 你安装的qt src 目录下

工欲善其事必先利其器

在这里插入图片描述

F10 下一步 F11 继续往里跳

看一下 QWidget 类的基本结构

在这里插入图片描述

继承了 QObject 这是 Qt 的很重要的基类 ,咱们不进去看了,
QpaintDevice 这个类我没进去看 这个看字面的意思就是画图装置类 那也就是我们画一个窗口
显示窗口的基类, 我们都先不看 要是一层一层看 那得看到明年…

Q_PROPERTY

这个宏大家应该都不陌生 用来在一个类中声明一个属性property,由于该宏是qt特有的,需要用moc进行编译,故必须继承于QObject类。

在这里插入图片描述

这个宏 给脚本和元对象系统用的,比如QtScript,QML,或者QObject::property/setProperty……
UI design 里面用
在其他地方也用不到了 。。。

说实话 咱们实现自己类 如果不用上面的东西 就没必要写
他这里 就是 窗口 width height
x ,y
color
颜色的设置

继续往下走

在这里插入图片描述

一个 构造 析构
下面 是 win ID
style 样式表的设置 获取
window 窗口的模式
在这里插入图片描述

设置模态窗口(显示在最顶层, 不关掉 后面的页面窗口不能点 )

类的函数 比较多 继续向下

在这里插入图片描述

这些看字面意思 都能看懂 也没必要看
窗口的一些 属性 大小 尺寸 乱七八糟的

继续向下 , 中间省略了部分 也是一些属性获取设置的 函数 就略过

在这里插入图片描述

实现了一些 虚函数 也是我们常见的
鼠标键盘事件 resize 移动 重绘 关闭 等等事件

在往下 就是 声明了一些 友元类
在这里插入图片描述

声明了友元类 就可以相互访问之间的变量和元素了

基本的就这些 看一下构造函数

构造函数

在这里插入图片描述
在这里插入图片描述

上来 捕获异常 如果 init 初始化失败 就 cleanup 清理一些申请的空间和资源 然后 抛出异常

继续看 进到 init() 里面看

在这里插入图片描述
我们都知道 Qt 有两种 事件循环
一种是 QcoreApplication 无GUI 的控制台的
一种是 QApplication GUI 的

如果是 QCoreApplication 就报错 返回

下面是判断父类 的 windowType 是个枚举 就是窗口的 类型

然后创建相应的子类

有什么窗口小部件 带标题栏的窗口 标题栏 工具栏 等乱七八糟的

在这里插入图片描述
在这里插入图片描述

线程中 是不能创建 窗口类的

窗口类 只能创建在 Qt 的主界面线程中 也就是带事件循环的 那个

在这里插入图片描述

初始化一些参数
窗口的属性

下面就是 选择默认的窗口大小 开始生成窗口

如果有父窗口 就 调整 window_flag
重新加载布局
父类 的字体 样式表啥的

在这里插入图片描述

我们看 create() 这个函数

在这里插入图片描述

Wid 窗口的句柄 也是唯一的标识号

然后根据父类的状态 createWinId();

createWinId()

在这里插入图片描述

生成winID 这里不用管 继续向下

还是在 Create 的函数体内 下面有个 create_sys

我认为到 创建窗口的 地方 进去看一下
在这里插入图片描述

create_sys()

在这里插入图片描述

怎么又创建了个 Qwindow

在看一下 QWindow 这个类吧

QWindow

在这里插入图片描述
继承 QSurface

QSurface

在这里插入图片描述

QSurface类是Qt中可呈现表面的抽象。
可以使用size()函数访问表面的大小。可以通过format()函数访问表面的呈现特定属性。

看到这里我都快 晕了
去看了下这个介绍
QSurface是一个可渲染的抽象类, 那应该就是 渲染窗口的基类

QWindow 的构造

直接看构造
在这里插入图片描述

在这里插入图片描述
到这里就把这个window 就加入到 管理list 中去了
到这里 一个 window 的初始化 就应该完成了

下面看一下窗口是怎么画出来的

show()

在这里插入图片描述

看下 SetVisible 上面两个函数也是调用的它

void QWidget::setVisible(bool visible)
{
    if (visible) { // show
        if (testAttribute(Qt::WA_WState_ExplicitShowHide) && !testAttribute(Qt::WA_WState_Hidden))
            return;

        Q_D(QWidget);

        // Designer uses a trick to make grabWidget work without showing
        if (!isWindow() && parentWidget() && parentWidget()->isVisible()
            && !parentWidget()->testAttribute(Qt::WA_WState_Created))
            parentWidget()->window()->d_func()->createRecursively();

        //create toplevels but not children of non-visible parents
        QWidget *pw = parentWidget();
        if (!testAttribute(Qt::WA_WState_Created)
            && (isWindow() || pw->testAttribute(Qt::WA_WState_Created))) {
            create();
        }

        bool wasResized = testAttribute(Qt::WA_Resized);
        Qt::WindowStates initialWindowState = windowState();

        // polish if necessary
        ensurePolished();

        // remember that show was called explicitly
        setAttribute(Qt::WA_WState_ExplicitShowHide);
        // whether we need to inform the parent widget immediately
        bool needUpdateGeometry = !isWindow() && testAttribute(Qt::WA_WState_Hidden);
        // we are no longer hidden
        setAttribute(Qt::WA_WState_Hidden, false);

        if (needUpdateGeometry)
            d->updateGeometry_helper(true);

        // activate our layout before we and our children become visible
        if (d->layout)
            d->layout->activate();

        if (!isWindow()) {
            QWidget *parent = parentWidget();
            while (parent && parent->isVisible() && parent->d_func()->layout  && !parent->data->in_show) {
                parent->d_func()->layout->activate();
                if (parent->isWindow())
                    break;
                parent = parent->parentWidget();
            }
            if (parent)
                parent->d_func()->setDirtyOpaqueRegion();
        }

        // adjust size if necessary
        if (!wasResized
            && (isWindow() || !parentWidget()->d_func()->layout))  {
            if (isWindow()) {
                adjustSize();
                if (windowState() != initialWindowState)
                    setWindowState(initialWindowState);
            } else {
                adjustSize();
            }
            setAttribute(Qt::WA_Resized, false);
        }

        setAttribute(Qt::WA_KeyboardFocusChange, false);

        if (isWindow() || parentWidget()->isVisible()) {
            d->show_helper();

            qApp->d_func()->sendSyntheticEnterLeave(this);
        }

        QEvent showToParentEvent(QEvent::ShowToParent);
        QApplication::sendEvent(this, &showToParentEvent);
    } else { // hide
        if (testAttribute(Qt::WA_WState_ExplicitShowHide) && testAttribute(Qt::WA_WState_Hidden))
            return;
#if 0 // Used to be included in Qt4 for Q_WS_WIN
        // reset WS_DISABLED style in a Blocked window
        if(isWindow() && testAttribute(Qt::WA_WState_Created)
           && QApplicationPrivate::isBlockedByModal(this))
        {
            LONG dwStyle = GetWindowLong(winId(), GWL_STYLE);
            dwStyle &= ~WS_DISABLED;
            SetWindowLong(winId(), GWL_STYLE, dwStyle);
        }
#endif
        if (QApplicationPrivate::hidden_focus_widget == this)
            QApplicationPrivate::hidden_focus_widget = 0;

        Q_D(QWidget);

        // hw: The test on getOpaqueRegion() needs to be more intelligent
        // currently it doesn't work if the widget is hidden (the region will
        // be clipped). The real check should be testing the cached region
        // (and dirty flag) directly.
        if (!isWindow() && parentWidget()) // && !d->getOpaqueRegion().isEmpty())
            parentWidget()->d_func()->setDirtyOpaqueRegion();

        setAttribute(Qt::WA_WState_Hidden);
        setAttribute(Qt::WA_WState_ExplicitShowHide);
        if (testAttribute(Qt::WA_WState_Created))
            d->hide_helper();

        // invalidate layout similar to updateGeometry()
        if (!isWindow() && parentWidget()) {
            if (parentWidget()->d_func()->layout)
                parentWidget()->d_func()->layout->invalidate();
            else if (parentWidget()->isVisible())
                QApplication::postEvent(parentWidget(), new QEvent(QEvent::LayoutRequest));
        }

        QEvent hideToParentEvent(QEvent::HideToParent);
        QApplication::sendEvent(this, &hideToParentEvent);
    }
}

在这里插入图片描述

看到这里 我也晕了 看不懂了 没有调用 Win32API 啊

我在网上查了一下 没找到
我猜这里 应该是 进入了事件循环
应该还有专门的一个渲染类 来调用 win32API 来绘制窗口

这我也找不到了 看来还是太菜

求助

路过大佬 给说一下 后面调用 Win32Api的 地方在哪里 哪个类 我去看一下源码

发布了194 篇原创文章 · 获赞 443 · 访问量 19万+

猜你喜欢

转载自blog.csdn.net/weixin_42837024/article/details/105122724