Snail

导航

< 2025年3月 >
23 24 25 26 27 28 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 1 2 3 4 5
统计
 

关于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.
    会向widget发UpdateRequest事件的就QWidgetBackingStore::sendUpdateRequest一个地方, 这个sendUpdateRequest又是给WidgetBackingStore::markDirty用的:
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这边的情况.
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的重绘.

posted on   Snail-0304  阅读(626)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
 
点击右上角即可分享
微信分享提示