QT是基于事件驱动的,消息处理逻辑如下:
主函数的逻辑:
复制代码
1
2
3
4
5
6
7
8
9
10
11
12#include "widget.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); Widget w; w.show(); return a.exec(); }
调用 QApplication::exec:
复制代码
1
2
3
4int QApplication::exec() { return QGuiApplication::exec(); }
调用 QGuiApplication::exec():
复制代码
1
2
3
4
5
6
7int QGuiApplication::exec() { #ifndef QT_NO_ACCESSIBILITY QAccessible::setRootObject(qApp); #endif return QCoreApplication::exec(); }
复制代码
1
2QCoreApplication::exec():
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27int QCoreApplication::exec() { if (!QCoreApplicationPrivate::checkInstance("exec")) return -1; QThreadData *threadData = self->d_func()->threadData; if (threadData != QThreadData::current()) { qWarning("%s::exec: Must be called from the main thread", self->metaObject()->className()); return -1; } if (!threadData->eventLoops.isEmpty()) { qWarning("QCoreApplication::exec: The event loop is already running"); return -1; } threadData->quitNow = false; QEventLoop eventLoop; self->d_func()->in_exec = true; self->d_func()->aboutToQuitEmitted = false; int returnCode = eventLoop.exec(); threadData->quitNow = false; if (self) self->d_func()->execCleanup(); return returnCode; }
调用eventLoop.exec():
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66int QEventLoop::exec(ProcessEventsFlags flags) { Q_D(QEventLoop); //we need to protect from race condition with QThread::exit QMutexLocker locker(&static_cast<QThreadPrivate *>(QObjectPrivate::get(d->threadData->thread.loadAcquire()))->mutex); if (d->threadData->quitNow) return -1; if (d->inExec) { qWarning("QEventLoop::exec: instance %p has already called exec()", this); return -1; } struct LoopReference { QEventLoopPrivate *d; QMutexLocker &locker; bool exceptionCaught; LoopReference(QEventLoopPrivate *d, QMutexLocker &locker) : d(d), locker(locker), exceptionCaught(true) { d->inExec = true; d->exit.storeRelease(false); ++d->threadData->loopLevel; d->threadData->eventLoops.push(d->q_func()); locker.unlock(); } ~LoopReference() { if (exceptionCaught) { qWarning("Qt has caught an exception thrown from an event handler. Throwingn" "exceptions from an event handler is not supported in Qt.n" "You must not let any exception whatsoever propagate through Qt code.n" "If that is not possible, in Qt 5 you must at least reimplementn" "QCoreApplication::notify() and catch all exceptions there.n"); } locker.relock(); QEventLoop *eventLoop = d->threadData->eventLoops.pop(); Q_ASSERT_X(eventLoop == d->q_func(), "QEventLoop::exec()", "internal error"); Q_UNUSED(eventLoop); // --release warning d->inExec = false; --d->threadData->loopLevel; } }; LoopReference ref(d, locker); // remove posted quit events when entering a new event loop QCoreApplication *app = QCoreApplication::instance(); if (app && app->thread() == thread()) QCoreApplication::removePostedEvents(app, QEvent::Quit); #ifdef Q_OS_WASM // Partial support for nested event loops: Make the runtime throw a JavaSrcript // exception, which returns control to the browser while preserving the C++ stack. // Event processing then continues as normal. The sleep call below never returns. // QTBUG-70185 if (d->threadData->loopLevel > 1) emscripten_sleep(1); #endif while (!d->exit.loadAcquire()) processEvents(flags | WaitForMoreEvents | EventLoopExec); ref.exceptionCaught = false; return d->returnCode.loadRelaxed(); }
QT绘制机制:
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96void QWidgetPrivate::setVisible(bool visible) { Q_Q(QWidget); if (visible) { // show // Designer uses a trick to make grabWidget work without showing if (!q->isWindow() && q->parentWidget() && q->parentWidget()->isVisible() && !q->parentWidget()->testAttribute(Qt::WA_WState_Created)) q->parentWidget()->window()->d_func()->createRecursively(); //create toplevels but not children of non-visible parents QWidget *pw = q->parentWidget(); if (!q->testAttribute(Qt::WA_WState_Created) && (q->isWindow() || pw->testAttribute(Qt::WA_WState_Created))) { q->create(); } bool wasResized = q->testAttribute(Qt::WA_Resized); Qt::WindowStates initialWindowState = q->windowState(); // polish if necessary q->ensurePolished(); // whether we need to inform the parent widget immediately bool needUpdateGeometry = !q->isWindow() && q->testAttribute(Qt::WA_WState_Hidden); // we are no longer hidden q->setAttribute(Qt::WA_WState_Hidden, false); if (needUpdateGeometry) updateGeometry_helper(true); // activate our layout before we and our children become visible if (layout) layout->activate(); if (!q->isWindow()) { QWidget *parent = q->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 && (q->isWindow() || !q->parentWidget()->d_func()->layout)) { if (q->isWindow()) { q->adjustSize(); if (q->windowState() != initialWindowState) q->setWindowState(initialWindowState); } else { q->adjustSize(); } q->setAttribute(Qt::WA_Resized, false); } q->setAttribute(Qt::WA_KeyboardFocusChange, false); if (q->isWindow() || q->parentWidget()->isVisible()) { show_helper(); qApp->d_func()->sendSyntheticEnterLeave(q); } QEvent showToParentEvent(QEvent::ShowToParent); QCoreApplication::sendEvent(q, &showToParentEvent); } else { // hide if (QApplicationPrivate::hidden_focus_widget == q) QApplicationPrivate::hidden_focus_widget = 0; // 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 (!q->isWindow() && q->parentWidget()) // && !d->getOpaqueRegion().isEmpty()) q->parentWidget()->d_func()->setDirtyOpaqueRegion(); q->setAttribute(Qt::WA_WState_Hidden); if (q->testAttribute(Qt::WA_WState_Created)) hide_helper(); // invalidate layout similar to updateGeometry() if (!q->isWindow() && q->parentWidget()) { if (q->parentWidget()->d_func()->layout) q->parentWidget()->d_func()->layout->invalidate(); else if (q->parentWidget()->isVisible()) QCoreApplication::postEvent(q->parentWidget(), new QEvent(QEvent::LayoutRequest)); } QEvent hideToParentEvent(QEvent::HideToParent); QCoreApplication::sendEvent(q, &hideToParentEvent); } }
paintEvent:
复制代码
1void paintEvent(QPaintEvent *event);
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39#include "widget.h" Widget::Widget(QWidget *parent) : QWidget(parent) { setMaximumSize(600,500); MyLabel * myLabel = new MyLabel(this); myLabel->setGeometry(0,0,300,300); myLabel->setText("hello,world"); } Widget::~Widget() { } void Widget::dealClick(bool flag){ qDebug() << flag; if (!flag){ lineEdit->undo(); } } void Widget::listChildrens(QWidget * widget){ QObjectList objectList = widget->children(); for (int i=0;i<objectList.size();i++){ qDebug() << objectList[i]->objectName(); qDebug() << objectList[i]->metaObject()->className(); listChildrens(qobject_cast<QWidget *>(objectList[i])); } }
总结:paibeEvent,被组件子类重写后,父类的绘制会调用paintEvent,所以会被重新绘制!!!
最后
以上就是敏感河马最近收集整理的关于QT源码剖析的全部内容,更多相关QT源码剖析内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复