Qt update刷新之源碼分析總結

  • 2021 年 3 月 13 日
  • 筆記

大家好,我是IT文藝男,來自一線大廠的一執行緒序員

經過前面幾次的Qt源碼講解,我相信大家對Qt update刷新機制從底層原理上有了一個深刻的理解;這次做一個收尾總結,來複盤前面幾次所講解的內容;

分析的切入點、思考點::

在做GUI開發時,要讓控制項刷新,會調用update函數;那麼在調用了update函數後,Qt究竟基於什麼原理、執行了什麼程式碼使得螢幕上有變化?

分析的過程分解::

一、刷新事件非同步投遞過程
二、刷新事件的處理流程
三、繪製到記憶體Image
四、刷新結果輸出到螢幕

一、刷新事件非同步投遞過程

分析void QWidget::update()函數的源碼,即調用update沒有傳遞參數,則默認刷新控制項的整個區域,調用重載的update函數

  1. 如果控制項是隱藏或者刷新被禁用,則直接返回
  2. 參數傳遞的矩形與控制項矩形的交集,如果為空,則直接返回
  3. 如果支援BackingStore(默認支援),則標臟該控制項所屬的頂層窗口(TLW:: topLevelWidget縮寫)區域,即調用tlwExtra->backingStoreTracker->markDirty(r, this);函數
    a、把控制項加入到dirtyWidgets容器中(addDirtyWidget函數)
    b、通知tlw進行刷新(sendUpdateRequest函數)
    sendUpdateRequest函數Post一個QEvent::UpdateRequest事件,即放入事件隊列中,立即返回;QEvent::UpdateRequest事件的接受者為tlw;

二、刷新事件的處理流程

追蹤QEvent::UpdateRequest事件處理,進入消息通知流程,即QApplication::notify(QObject *receiver, QEvent *e)函數(沒有對QEvent::UpdateRequest事件進行處理),進一步由QApplicationPrivate::notify_helper(QObject *receiver, QEvent * e)函數處理;

receiver的event函數不做處理,其調用父類的event函數,即bool QWidget::event(QEvent *event)函數,該函數中針對事件類型進行處理(switch case);

對於QEvent::UpdateRequest事件處理,QWidgetBackingStore::doSync函數中調用tlw->d_func()->drawWidget(store->paintDevice(), dirtyCopy, QPoint(), flags, 0, this);函數進行繪製,函數的第一個參數是獲取繪製設備,對於Windows平台,繪製目的設備為記憶體Image

三、繪製到記憶體Image

回到QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QPoint &offset, int flags,QPainter *sharedPainter, QWidgetBackingStore *backingStore)函數

函數主體內容如下::
1、繪製背景
2、繪製前景(send the paint event)
3、繪製子控制項(paintSiblingsRecursive函數調用)

QWidgetPrivate::paintSiblingsRecursive函數里又會調用QWidgetPrivate::drawWidget函數從而形成樹形繪製

四、刷新結果輸出到螢幕

qtbase\src\plugins\platforms\windows目錄中的QWindowsBackingStore::flush函數中會調用BitBlt函數(Windows API函數)

關注我的微信公眾號(itwenyinan)下載完整的講解影片、PPT、Code;

下載後包括如下內容::