其他分享
首页 > 其他分享> > 关于backingStore和updateRequest事件

关于backingStore和updateRequest事件

作者:互联网

关于backingStore的同步

QWidgetBackingStore::sync说起, 调用关系如下:

QWidgetPrivate::syncBackingStore
    => QWidgetBackingStore::sync
        => QWidgetBackingStore::markDirtyOnScreen
        => QWidgetBackingStore::doSync
            => QWidgetBackingStore::resetWidget
            => QWidgetPrivate::drawWidget
                => QWidgetPrivate::paintBackground
                => QWidgetPrivate::sendPaintEvent
                    => QWidget::paintEvent
                => QWidgetPrivate::paintSiblingsRecursive
            => QWidgetBackingStore::flush

QWidgtBackingStore只对QWidget可见, 所以QWidgetPrivate::syncBackingStoreQWidgetBackingStore::sync做了进一步封装, 其他地方可以通过widget的D指针调到QWidgetPrivate::syncBackingStore.
QWidgetPrivate::syncBackingStore主要是QWdiget在处理UpdateRequest事件的时候调到:

QWidget::event(QEvent::UpdateRequest)
    => QWidgetPrivate::syncBackingStore

关于updateRequest事件

至于UpdateRequest事件的来源, 搜代码, 找到的就QWidgetBackingStoreQWidgetWindow(QWindow)这两个地方.

QWidgetBackingStore::markDirty (updateNow)
    => QWidgetBackingStore::addDirtyWidget
    => QWidgetBackingStore::sendUpdateRequest
        => QApplication::sendEvent(widget, QEvent::UpdateRequest) (or postEvent)

再上一层就到了QWidget::repaintQWidget::update:

QWidget::repaint(const QRegion &rgn)
    => QWidgetPrivate::repaint
        => QWidgetBackingStore::markDirty (updateNow)


QWidget::update(const QRect &rect)
    => QWidgetPrivate::update
         => QWidgetBackingStore::markDirty (updateLatter)

这两个算是QWidget最终暴露给上层应用的api了. 看实现都是调的QWidgetBackingStore::markDirty, 不同之处仅是传的参数, 前者是立即触发UpdateRequest事件, 后者也会触发UpdateReques事件但是走的是事件循环.

repaint最终会立即触发paintEvent, 多用于动画的绘制.

连续多次调update最终只会触发一次paintEvent. 因为QApplication::compressEvent中对UpdateRequest事件做了压缩. 算是Qt做的一点优化. Qt也是比较建议用update.

按钮hover效果的刷新就是在处理鼠标事件的时候调了QWidget::update.

QWidgetWindow::event(QEvent::Resize)
    => QWidgetWindow::handleResizeEvent
        => QWidgetPrivate::syncBackingStore

QWidgetWindow::event(QEvent::Expose)
    => QWidgetWindow::handleExposeEvent
        => QWidgetPrivate::syncBackingStore

QWidgetWindow::repaintWindow()
    => QWidgetBackingStore::markDirty(updateNow, BufferInvalid)

QWindow::requestUpdate
    => QPlatformWindow::requestUpdate
        => QPlatformWindow::deliverUpdateRequest
             => QCoreApplication::sendEvent(window, QEvent::UpdateRequest);
                => QWidgetWindow::event(QEvent::UpdateRequest)
                    => QWidget::repaint

看了下, QWidgetWindow这边会触发到backingStore更新的有上面四个地方. 前面两个两个很好理解, 窗口大小改变(Resize)和窗口显示(Expose)的时候会触发. 第三个和屏幕相关的, 从QWindow::setScreen触发过来的, 场景未知, 先略过.

至于最后一个, QWidgetWindow在处理UpdateRequest事件的时候会触发widget的重绘. 这个UpdateRequest事件最终来自QWindow::requestUpdate, 是暴露给上层应用的api. 只能说Qt的设计就是如此,QWindow::requestUpdate向本窗口发一个UpdateRequest事件,
然后派生类QWidgetWindow在处理UpdateRequest事件的时候转调widget的重绘.

标签:QWidgetPrivate,syncBackingStore,QWidgetBackingStore,UpdateRequest,QWidgetWindow,
来源: https://www.cnblogs.com/snail-0304/p/16645162.html