qt paintEvent


基礎概念:

paintEvent(QPaintEvent*)函數是QWidget類中的虛函數,用於ui的繪制,會在多種情況下被其他函數自動調用,比如update()時。

運行時機:

一個重繪事件用來重繪一個部件的全部或者部分區域,下面幾個原因的任意一個都會發生重繪事件:

(1)repaint()函數或者update()函數被調用;

(2)被隱藏的部件現在被重新顯示;

(3)其他一些原因。

優化繪制事件方法:

        1.大部分部件可以簡單地重繪它們的全部界面,但是一些繪制比較慢的部件需要進行優化而只繪制需要的區域(可以使用QPaintEvent::region()來獲取該區域),這種速度上的優化不會影響結果。

        2.Qt也會通過合並多個重繪事件為一個事件來加快繪制,當update()函數被調用多次,或者窗口系統發送了多個重繪事件,那么Qt就會合並這些事件成為一個事件,而這個事件擁有最大的需要重繪的區域。update()函數不會立即進行重繪,要等到Qt返回主事件循環后才會進行,所以多次調用update()函數一般只會引起一次paintEvent()函數調用。

        3.而調用repaint()函數會立即調用paintEvent()函數來重繪部件,只有在必須立即進行重繪操作的情況下(比如在動畫中),才使用repaint()函數。

        4.update()函數允許Qt優化速度和減少閃爍,但是repaint()函數不支持這樣的優化,所以建議一般情況下盡可能使用update()函數。

        5.還要說明一下,在程序開始運行時就會自動發送重繪事件而調用paintEvent()函數,另外,不要在paintEvent()函數中調用update()或者repaint()函數。

        6.當重繪事件發生時,要更新的區域一般會被擦除,然后在部件的背景上進行繪制。

如何重新實現paintevent:

       怎么畫?

       在那里畫?

       用什么畫?

1.QPainter類

       這個類主要提供在窗體或者其他繪圖設備上進行繪圖的功能,

       在paintEvent(QPaintEvent*)中使用如下:QPainter painter(this);  

       此類中常用的函數有:

       drawXXX()函數,用於繪制圖形、文字和路徑等;

       fillXXX()函數,用於填充,可在指定區域內進行填充;

       brush()和pen()  筆刷和鋼筆的相關操作

2.QPainterPath類

        這個類為繪圖提供容器,主要還是用於描述繪制路徑。

        可以通過函數setFillRule(Qt::WindingFill);

        來設置填充規則,通過addRect()函數來添加繪制區域。

 

3.QColor類

此類提供顏色支持,這里的顏色可以定義四個屬性:QColor ( int r, int g, int b, int a = 255 ),即紅、綠、藍和透明度。除此之外,也可以單個設置這四個值,通過類似setAlpha()的函數即可設置,這對設計漸進效果很有幫助。

 

例如:
void ABC::paintEvent(QPaintEvent *)  
{  
    QPainterPath path;  
    path.setFillRule(Qt::WindingFill);  
    path.addRect(10, 10, this->width()-20, this->height()-20);  
  
    QPainter painter(this);  
    painter.setRenderHint(QPainter::Antialiasing, true);  
    painter.fillPath(path, QBrush(Qt::white));  
  
    QColor color(0, 0, 0, 50);  
    for(int i=0; i<10; i++)  
    {  
        QPainterPath path;  
        path.setFillRule(Qt::WindingFill);  
        path.addRect(10-i, 10-i, this->width()-(10-i)*2, this->height()-(10-i)*2);  
        color.setAlpha(150 - qSqrt(i)*50);  
        painter.setPen(color);  
        painter.drawPath(path);  
    }  


其他相關函數:

一.主要理解一下幾個方法和屬性:

1.QWidget * QScrollView::viewport () const

2.void QWidget::paintEvent ( QPaintEvent * ) [虛 保護]

3.void QWidget::repaint ( int x, int y, int w, int h, bool erase = TRUE ) [槽]

4.void QWidget::update () [槽]

5.void QWidget::erase ( int x, int y, int w, int h )

6.bool updatesEnabled

二.現分別詳細介紹:

1.QWidget * QScrollView::viewport () const

返回滾動視圖中的視口窗口部件,這個窗口部件包含內容窗口部件或者要畫的區域。

2.void QWidget::paintEvent ( QPaintEvent * ) [虛 保護]

只要窗口部件需要被重繪就被調用。

每個要顯示輸出的窗口部件必須實現它。

這個事件處理器可以在子類中被重新實現來接收繪制事件。 它可以是repaint()或update()的結果。

很多窗口部件在當它們被請求時,它們很簡單地重新繪制整個界面,但是一些窗口部件通過僅僅繪制被請求的區域QPaintEvent::region()進 行優化,例如,QListView和QCanvas就是這樣做的。

Qt也可通過把多個繪制事件合並為一個來加快繪制速度。當update()被調用幾次或者窗口系統發送幾次繪制事件,Qt把它們合並為 一個比較大區域(請參考QRegion::unite())的一個事件中。repaint()不允許這樣優化,所以只要可能我們盡量使用update ()。

當繪制事件發生,更新區域通常被擦除。這里有一些例外,通過QPaintEvent::erased()可以得知這個窗口部件是否被擦除。

3.void QWidget::repaint ( int x, int y, int w, int h, bool erase = TRUE ) [槽]

通過立即調用paintEvent()來直接重新繪制窗口部件,如果erase為真,Qt在paintEvent()調用之前擦除區域 (x,y,w,h)。 如果w是負數,它被width()-x替換,並且如果h是負數,它被height()-y替換。

如果你需要立即重新繪制,建議使用repaint(),比如在動畫期間。

在絕大多數情況下,update()更好,因為它允許Qt來優化速度並且防止閃 爍。 警告:如果你在一個函數中調用repaint(),而它自己又被paintEvent()調用,你也許會看到無線循環。update()函數從來不會產生 循環。

4.void QWidget::update () [槽]

更新窗口部件,當Qt回到主事件中時,它規划了所要處理的繪制事件。這樣允許Qt進行優化從而得到比調用repaint()更快的速度和更 少的閃爍。 幾次調用update()的結果通常僅僅是一次paintEvent()調用。 Qt通常在paintEvent()調用之前擦除這個窗口部件的區域,僅僅只有在WRepaintNoErase窗口部件標記被設置的時候才不會。

5.void QWidget::erase ( int x, int y, int w, int h )

在窗口部件中擦除指定區域(x, y, w, h),並不產生繪制事件。

如果w為負數,它被width()-x替換。如果h為負數,它被height()-y替換。

子窗口部件不被影響。

6.bool updatesEnabled

這個屬性保存的是更新是否生效。

如果更新失效,調用update()和repaint()是沒有效果的。

如果更新失效,來自窗口系統的繪制事件會被正常處理。

setUpdatesEnabled()通常被用於在一小段事件內使更新失效,例如為了避免在大的變化期間發生屏幕閃爍。

實例:

    setUpdatesEnabled( FALSE );

    bigVisualChanges();

    setUpdatesEnabled( TRUE );

    repaint();

通過setUpdatesEnabled()設置屬性值並且通過isUpdatesEnabled()來獲得屬性值。
---------------------
作者:feiyu_qq
來源:CSDN
原文:https://blog.csdn.net/u012151242/article/details/78947024
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!


免責聲明!

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



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