【Qt笔记】5.QWidget源码查阅

1 概述

QWidget类是所有用户界面对象的基类。从QObject和QPaintDevice里继承过来

class Q_WIDGETS_EXPORT QWidget : public QObject, public QPaintDevice

由上可以看出qt是把其封装成dll供外部接口调用。
我们在实际项目中使用QWidget会发现其调用到的头文件都是编译器的
形式如下:
D:\QT\5.14.2\mingw73_32\include\QtWidgets\qwidget.h

其实际的源码位置如下路径
D:\QT\5.14.2\Src\qtbase\src\widgets\kernel\qwidget.cpp

其中涉及的相关的文件有如下几个:

D:\QT\5.14.2\Src\qtbase\src\widgets\kernel\qtwidgetsglobal_p.h
D:\QT\5.14.2\Src\qtbase\src\widgets\kernel\qtwidgetsglobal.h
D:\QT\5.14.2\Src\qtbase\src\widgets\kernel\qwidget.cpp
D:\QT\5.14.2\Src\qtbase\src\widgets\kernel\qwidget_p.h
D:\QT\5.14.2\Src\qtbase\src\widgets\kernel\qwidget.h

在这里插入图片描述

2 相关成员函数详解

2.1 构造函数

看一个类我们大致都会从其构造函数出发。

QWidget::QWidget(QWidget *parent, Qt::WindowFlags f)
    : QObject(*new QWidgetPrivate, 0), QPaintDevice()
{
    QT_TRY {
        d_func()->init(parent, f);
    } QT_CATCH(...) {
        QWidgetExceptionCleaner::cleanup(this, d_func());
        QT_RETHROW;
    }
}

这个代码有做异常处理.我们直接看init的操作即可。
init中传入父类的指针,并且传进去Qt::WindowFlags
该WindowFlags相关值如下: 可以直接看Qt助手里的描述
qt助手路径如下:
D:\QT\5.14.2\mingw73_32\bin\assistant.exe

ValueDescription
Qt::Widget是一个窗口或部件,有父窗口就是部件,没有就是窗口
Qt::Window是一个窗口,有窗口边框和标题
Qt::Dialog是一个对话框窗口
Qt::Sheet是一个窗口或部件Macintosh表单
Qt::Drawer是一个窗口或部件Macintosh抽屉,去掉窗口左上角的图标
Qt::Popup是一个弹出式顶层窗口
Qt::Tool是一个工具窗口
Qt::ToolTip是一个提示窗口,没有标题栏和窗口边框
Qt::SplashScreen是一个欢迎窗口,是QSplashScreen构造函数的默认值
Qt::Desktop是一个桌面窗口或部件
Qt::SubWindow是一个子窗口

init中会直接调用到

void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f)

QWidget中的一些操作都是间接通过QWidgetPrivate去操作,去耦做的非常的规范.

在init中首先会创建QCoreApplication的instance

    if (Q_UNLIKELY(!qobject_cast<QApplication *>(QCoreApplication::instance())))
        qFatal("QWidget: Cannot create a QWidget without QApplication");

父类中插入

    Q_ASSERT(allWidgets);
    if (allWidgets)
        allWidgets->insert(q);

    int targetScreen = -1;
    if (parentWidget && parentWidget->windowType() == Qt::Desktop) {
        const QDesktopScreenWidget *sw = qobject_cast<const QDesktopScreenWidget *>(parentWidget);
        targetScreen = sw ? sw->screenNumber() : 0;
        parentWidget = 0;
    }

这是allWidgets的声明
QWidgetSet *QWidgetPrivate::allWidgets = 0; // widgets with no wid
操作完父类的一些赋值和插入后,需要设置一些相关的属性并传递相关事件

setAttribute()

分发事件

    QEvent e(QEvent::Create);
    QCoreApplication::sendEvent(q, &e);
    QCoreApplication::postEvent(q, new QEvent(QEvent::PolishRequest));

    extraPaintEngine = 0;

2.2 设置尺寸

最小尺寸获取

QSize QWidget::minimumSize() const
{
    Q_D(const QWidget);
    return d->extra ? QSize(d->extra->minw, d->extra->minh) : QSize(0, 0);
}

最大尺寸的获取

QSize QWidget::maximumSize() const
{
    Q_D(const QWidget);
    return d->extra ? QSize(d->extra->maxw, d->extra->maxh)
                 : QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
}

设置固定的尺寸,最大最小尺寸设置都是其中的一部分。

void QWidget::setFixedSize(int w, int h)
{
    Q_D(QWidget);
    bool minSizeSet = d->setMinimumSize_helper(w, h);
    bool maxSizeSet = d->setMaximumSize_helper(w, h);
    if (!minSizeSet && !maxSizeSet)
        return;

    if (isWindow())
        d->setConstraints_sys();
    else
        d->updateGeometry_helper(true);

    if (w != QWIDGETSIZE_MAX || h != QWIDGETSIZE_MAX)
        resize(w, h);
}

2.3 槽函数

仅仅举例关闭的槽函数

bool QWidget::close()
{
    return d_func()->close_helper(QWidgetPrivate::CloseWithEvent);
}

关闭的时候需要把相关的事件分发下去

   if (mode == CloseWithSpontaneousEvent)
            QApplication::sendSpontaneousEvent(q, &e);
        else
            QCoreApplication::sendEvent(q, &e);

...
//最后通过QCoreApplicationPrivate中的方法去销毁实例
            QCoreApplicationPrivate *applicationPrivate = static_cast<QCoreApplicationPrivate*>(QObjectPrivate::get(QCoreApplication::instance()));
            applicationPrivate->maybeQuit();
...
//在其使用完后,正确设置相关的关闭属性,并销毁相关的对象
    if (!that.isNull()) {
        data.is_closing = 0;
        if (q->testAttribute(Qt::WA_DeleteOnClose)) {
            q->setAttribute(Qt::WA_DeleteOnClose, false);
            q->deleteLater();
        }
    }            

公共槽函数有如下:
在这里插入图片描述
同时QWidget提供了如下Signals,从名字可以看出其相关的发射情况

void customContextMenuRequested(const QPoint &pos)
void windowIconChanged(const QIcon &icon)
void windowTitleChanged(const QString &title)

而bool QWidget::event(QEvent *event)用来处理鼠标按建等其他相关事件的处理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

辰辰大美女呀

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

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

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

打赏作者

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

抵扣说明:

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

余额充值