1. 程式人生 > >Qt update重新整理之原始碼分析總結

Qt update重新整理之原始碼分析總結

大家好,我是IT文藝男,來自一線大廠的一執行緒序員 經過前面幾次的Qt原始碼講解,我相信大家對Qt update重新整理機制從底層原理上有了一個深刻的理解;這次做一個收尾總結,來複盤前面幾次所講解的內容; ## 分析的切入點、思考點:: 在做GUI開發時,要讓控制元件重新整理,會呼叫update函式;那麼在呼叫了update函式後,Qt究竟基於什麼原理、執行了什麼程式碼使得螢幕上有變化? ## 分析的過程分解:: **一、重新整理事件非同步投遞過程** **二、重新整理事件的處理流程** **三、繪製到記憶體Image** **四、重新整理結果輸出到螢幕** ### 一、重新整理事件非同步投遞過程 分析`void QWidget::update()`函式的原始碼,即呼叫update沒有傳遞引數,則預設重新整理控制元件的整個區域,呼叫過載的update函式 1. **如果控制元件是隱藏或者重新整理被禁用,則直接返回** 1. **引數傳遞的矩形與控制元件矩形的交集,如果為空,則直接返回** 1. **如果支援BackingStore(預設支援),則標髒該控制元件所屬的頂層視窗(TLW:: topLevelWidget縮寫)區域,即呼叫`tlwExtra->backingStoreTracker->markDirty(r, this);`函式** a、**把控制元件加入到dirtyWidgets容器中(addDirtyWidget函式)** b、**通知tlw進行重新整理(`sendUpdateRequest`函式)** `sendUpdateRequest`函式**Post**一個**QEvent::UpdateRequest**事件,即放入事件佇列中,立即返回;QEvent::UpdateRequest事件的接受者為tlw; ![](https://img2020.cnblogs.com/blog/371367/202103/371367-20210313121746093-1421621049.png) ### 二、重新整理事件的處理流程 追蹤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 ![](https://img2020.cnblogs.com/blog/371367/202103/371367-20210313121913127-903152140.png) ### 三、繪製到記憶體Image 回到`QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QPoint &offset, int flags,QPainter *sharedPainter, QWidgetBackingStore *backingStore)`函式 ![](https://img2020.cnblogs.com/blog/371367/202103/371367-20210313122005389-1693802834.png) **函式主體內容如下::** **1、繪製背景** **2、繪製前景(send the paint event)** **3、繪製子控制元件(paintSiblingsRecursive函式呼叫)** QWidgetPrivate::paintSiblingsRecursive函式裡又會呼叫QWidgetPrivate::drawWidget函式從而形成**樹形繪製**。 ### 四、重新整理結果輸出到螢幕 qtbase\src\plugins\platforms\windows目錄中的`QWindowsBackingStore::flush`函式中會呼叫**BitBlt**函式(Windows API函式) ![](https://img2020.cnblogs.com/blog/371367/202103/371367-20210313122029593-931686249.png) ## 關注我的微信公眾號(itwenyinan)下載完整的講解視訊、PPT、Code; ![](https://img2020.cnblogs.com/blog/371367/202103/371367-20210313122114673-1012494201.jpg) ## 下載後包括如下內容:: ![](https://img2020.cnblogs.com/blog/371367/202103/371367-20210313122152273-9217008