Qt update重新整理之原始碼分析總結
阿新 • • 發佈:2021-03-13
大家好,我是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