【Qt笔记】5.QWidget源码查阅
文章目录
- 1 概述
- 2 相关成员函数详解
-
- 2.1 构造函数
- 2.2 设置尺寸
- 2.3 槽函数
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
Value | Description |
---|---|
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();elsed->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);elseQCoreApplication::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)用来处理鼠标按建等其他相关事件的处理。