Qt update刷新之源碼分析總結


大家好,我是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;

下載后包括如下內容::


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM