基礎概念:
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
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!