QT學習=====QPainter,PaintEvent,setRenderHint(防止圖形走樣)

https://jingyan.baidu.com/article/ad310e80cd7bf61849f49ec9.html

update();

repaint();

Qt裏面的重繪和Windows編程裏面的重繪差不多。但是Qt的重繪更有特色,更加智能。

在講之前,先說說paintEvent()

paintEvent()是一個虛函數槽(slot),子類可以對父類的paintEvent進行重寫。當調用 update(),repaint()的時候,paintEvent()會被調用,另外,當界面有任何改變的時候,paintEvent()也會被調用,這種界面的改變包括界面從隱藏到顯示,界面尺寸改變,當然還包括界面內容改變的時候會被調用。paintEvent()是已經被高度優化過的函數,它本身已經自動開啓並實現了雙緩衝(X11系統需要手動去開啓雙緩衝),因此Qt中重繪不會引起任何閃爍。

有了paintEvent的知識,現在再來看看update()和repaint()

update和repaint是一類的,需要重繪的對象主動去調用,然後重繪。update和repaint調用之後,都回去調用paintEvent().

repaint(),被調用之後,立即執行重繪,因此repaint是最快的,緊急情況下需要立刻重繪的可以使用repaint()。但是調用 repaint的函數不能放到paintEvent中調用。舉個例子:有一個繼承於QWidget的子類MyWidget,並在子類中對 paintEvent進行了重寫。我們在MyWidget::myrepaint()中調用repaint()。但是,myrepaint()又被重寫的 paintEvent()調用。這樣調用repaint()的函數又被paintEvent()調用,由於repaint()是立即重繪,而且repaint()在調用 paintEvent之前幾乎不做任何優化操作,而是會造成死循環,即:先調用repaint(),繼而調用 paintEvent(),paintEvent()反過來有調用repaint()…如此死循環。

update()跟repaint()比較,update則更加有優越性。update()調用之後並不是立即重繪,而是將重繪事件放入主消息循環中,由main的event loop來統一調度的(其實也是比較快的)。update在調用paintEvent之前,還做了很多優化,如果update被調用了很多次,最後這些 update會合併到一個大的重繪事件加入到消息隊列,最後只有這個大的update被執行一次。同時也避免了repaint()中所提到的死循環。因此,一般情況下,我們調用update就夠了,跟repaint()比起來,update是推薦使用的。

如果在paintEvent中有改變某一個變量(假設爲a)值的代碼,這個時候要注意,調用update後,如果顯示a的值,則此時由於updata()沒有立即執行,a的值並沒有改變。而調用repaint()又引起閃爍,這個時候可以考慮將改變變量a的值的代碼改寫到paintEvent()的外

Qt中的函數應用

反走樣技術

painter.setRenderHint(QPainter::Antialiasing, true); // 抗鋸齒

案例:


    QPainter painter(this);
    painter.setPen(QPen(Qt::black,5,Qt::DashDotLine,Qt::RoundCap));
    painter.setBrush(Qt::yellow);
    painter.drawEllipse(50,150,200,150);

    painter.setRenderHint(QPainter::Antialiasing,true);
    painter.setPen(QPen(Qt::black,5,Qt::DashDotDotLine,Qt::RoundCap));
    painter.setBrush(Qt::yellow);
    painter.drawEllipse(300,150,200,150);

QPainter函數參數:
painter.setPen(QPen(Qt::black, 5, Qt::DashDotLine, Qt::RoundCap));
第一個參數: 畫筆的顏色: black
第二個參數: 畫筆的粗細: 5px
第三個參數: 畫筆的類型: DashDotLine(線和點相間)
: 用了一個圓形的筆冒
用了一個黃色填充了圓(從50,150)處開始畫,然後在半徑爲200(橫向),150(縱向)

antialiasing 防止走樣

QPainter是一個狀態機,因此,只要這裏我們打開了它,之後所有
的代碼都會是反走樣繪製的了。

看到這裏你會發現,反走樣的效果其實比不走樣要好得多,那麼,爲什麼不默認打開反走樣呢?
這是因爲,反走樣是一種比較複雜的算法,在一些對圖像質量要求不高的應用中,
是不需要進行反走樣的。爲了提高效率,一般的圖形繪製系統, 如Java2D、
OpenGL之類都是默認不進行反走樣的。

還有一個疑問,既然反走樣比不反走樣的圖像質量高很多,不進行反走樣的繪製還有什麼作用呢?
答:(1) 前面說的是一個方面,也就是,在一些對圖像質量要求不高的環境下,或者說性能受
限的環境下,比如嵌入式和手機環境,是不必須要進行反走樣的。
(2)另外還有一點,在一些必須精確操作像素的應用中,也是不能進行反走樣的。

Photoshop裏面的鉛筆工具是不進行反走樣,而畫筆是要進行反走樣的。在放大的情況下就會知道,
有反走樣的情況下是不能進行精確到1像素的操作的。因爲反走樣很難讓你控制到1個像素。這不是
Photoshop畫筆工具的缺陷,而是反走樣算法的問題。如果你想了解爲什麼這樣,請查閱計算機圖
形學裏面關於反走樣的原理部分。

DrewLine進行畫線:
“`

  QPainter painter(this);
  QPen pen; // 調整線條寬度
  pen.setWidth(2);
  painter.setPen(pen);
  painter.setRenderHint(QPainter::Antialiasing,true);

 for(int i=0;i<100;i++)
 {
 painter.drawLine(20+ 10 * i, 20, 20+ 10 * i, size().height() - 20);
 從(20,20)開始,到(20,h-20)結束,依次縱座標向橫座標向有右偏移
 painter.drawLine(20, 20 + 10 * i, size().width() - 20, 20 + 10 * i);
 從(20,20)開始,到(w-20,20)結束,依次縱座標向後偏移10
 }

“`
DrawLine的參數介紹,(int x1,int y1,int x2,int y2)

發佈了57 篇原創文章 · 獲贊 35 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章