update过程
1.刷新事件的异步投递
首先调用QWidget的update:
void QWidgetPrivate::update(T r)
{
Q_Q(QWidget);
// 1、 如果控件是隐藏或者刷新被禁止,则直接返回
if (!q->isVisible() || !q->updatesEnabled())
return;
// 2、 参数传递的矩形与控件矩形的交集为空,则直接返回
T clipped = r & q->rect();
if (clipped.isEmpty())
return;
if (q->testAttribute(Qt::WA_WState_InPaintEvent)) {
QCoreApplication::postEvent(q, new QUpdateLaterEvent(clipped));
return;
}
// 3、 标脏该控件所属的顶层窗口(TLW:topLevelWidget)
QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
if (tlwExtra && tlwExtra->backingStore)
tlwExtra->repaintManager->markDirty(clipped, q);
}
markDirty里面执行内容如下:
void QWidgetRepaintManager::markDirty(const T &r, QWidget *widget, UpdateTime updateTime, BufferState bufferState)
{
、、、
// updateTime默认为UpdateLater
// 把控件加入到dirtyWidget容器中
// 通知tlw进行刷新sendUpdateRequest
if (dirtyWidgets.isEmpty()) {
addDirtyWidget(widget, r);
sendUpdateRequest(tlw, updateTime);
return;
}
、、、
}
sendUpdateRequest里面执行内容如下:
其post一个QEvent::UpdateRequest事件,放入事件队列中立即返回;QEvent::UpdateRequest事件的接受者为tlw。
void QWidgetRepaintManager::sendUpdateRequest(QWidget *widget, UpdateTime updateTime)
{
、、、
switch (updateTime) {
case UpdateLater:
updateRequestSent = true;
QCoreApplication::postEvent(widget, new QEvent(QEvent::UpdateRequest), Qt::LowEventPriority);
break;
case UpdateNow: {
QEvent event(QEvent::UpdateRequest);
QCoreApplication::sendEvent(widget, &event);
break;
}
}
、、、
}
2.刷新事件处理流程
继续追踪QEvent::UpdateRequest事件处理,进入消息通知流程,即QApplicaion::notify,进一步有QApplicationPrivate::notify_helper函数处理
bool QApplicationPrivate::notify_helper(QObject *receiver, QEvent * e)
{
// 1、send to all application event filters(application的事件过滤器处理)
if (threadRequiresCoreApplication()
&& receiver->d_func()->threadData.loadRelaxed()->thread.loadAcquire() == mainThread()
&& sendThroughApplicationEventFilters(receiver, e)) {
filtered = true;
return filtered;
}
// 2、send to all receiver event filters(receiver的事件过滤器处理)
if (sendThroughObjectEventFilters(receiver, e)) {
filtered = true;
return filtered;
}
// 3、deliver the event(调用receiver的event函数处理)
consumed = receiver->event(e);
}
最终调用父类QWidget::event函数进行处理:
bool QWidget::event(QEvent *event)
{
Q_D(QWidget);
case QEvent::UpdateRequest:
d->syncBackingStore();
break;
}
void QWidgetPrivate::syncBackingStore(const QRegion ®ion)
{
if (shouldPaintOnScreen())
paintOnScreen(region);
else if (QWidgetRepaintManager *repaintManager = maybeRepaintManager()) {
repaintManager->sync(q_func(), region);
}
}
3.绘制到内存
void QWidgetRepaintManager::paintAndFlush()
{
}
void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QPoint &offset, DrawWidgetFlags flags,
QPainter *sharedPainter, QWidgetRepaintManager *repaintManager)
{
}
void QWidgetPrivate::paintSiblingsRecursive(QPaintDevice *pdev, const QObjectList& siblings, int index, const QRegion &rgn,
const QPoint &offset, DrawWidgetFlags flags
, QPainter *sharedPainter, QWidgetRepaintManager *repaintManager)
{
}
4.刷新结果输出到屏幕
void QBackingStore::flush(const QRegion ®ion, QWindow *window, const QPoint &offset)
{
}
void QWindowsBackingStore::flush(QWindow *window, const QRegion ®ion,
const QPoint &offset)
{
// 调用BitBlt
}