文章目录
- 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();
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)用来处理鼠标按建等其他相关事件的处理。