C++ Qt學習筆記(4)繪圖

        Qt中的二維繪圖基本功能是使用Qpainter在繪圖設備上進行繪圖,繪圖設備由QpainterDevice提供,QPaintDevice是一個二維空間的抽象,可以使用QPainter在其上進行繪製,它是所有可以進行繪製的對象的基類。QPainterDevice的子類主要有QWidget, QPixmap,QPicture,QImage,QPinter,QOpenGIPainterDevice,這些設備相當於爲QPainter提供了一個畫布。通過繪製一些基本的圖形,如點,線,圓組成自己需要的圖圖件,形,得到的圖形是不可交互的。

       Qt中的Graphics View架構,使用QGraphicsView,QGraphicsScene,QGraphicsItem類繪圖,在一個場景中可以繪製,且圖件是可以交互的。

1. QPainter基本繪圖:

        在繪圖系統中,主要通過QPainter完成具體的繪圖操作,QPaintDevice是一個可以用QPainter進行繪圖的抽象二維畫布。QPainterEngine爲QPainter提供在不同設備上進行繪圖的接口,QPainterEngine類一般只在QPainter類和QPaintDevice類的內部使用,一般不需要我們去操作它。

       QPainter在一個Paint Event事件函數中進行繪圖,從畫布(QWidget, QPixmap, QPicture, QImage, QPinter,     QOpenGIPainterDevice )繼承的類都有Paint Event事件函數。例如創建一個Widget窗口,進行繪圖,則這個Widget窗口就是需要使用的繪圖設備。

       繪圖的區域就是Widget內部的區域,區域內的座標系統的單位是像素,左上角爲原點(0,0),向右是X軸正向,向下是Y軸正向。繪圖區域的大小可以由Widget::width()以及Widget::height()得到。

QPainter繪圖的屬性:
1. pen屬性:是一個QPen對象,用於控制線條的顏色,寬度,線型等屬性

2. brush屬性:是一個QBrush對象,控制區域填充特性,如顏色,填充方式,漸變特性

3. font:QFont對象,用於繪製文字時控制文字的屬性,字體,大小等

1. 首先聲明繪圖事件處理函數:

protected:
    void paintEvent(QPaintEvent* event);

2.在paintEvent()函數中編寫繪製圖像的代碼:

void Widget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);    // this代表Widget,及繪圖設備
    painter.setRenderHint(QPainter::Antialiasing);    // 繪畫普通圖形啓用反走樣, 即開啓抗鋸齒
    painter.setRenderHint(QPainter::TextAntialiasing);    // 繪畫文字反走樣, 即開啓抗鋸齒
    int width = this->width();      // 獲取繪圖區域的大小
    int height = this->height();

    QRect rect(width/4, height/4, width/2, height/2);   // 中間區域矩形框
    // QPainter屬性 pen,brush,font
    QPen pen;
    pen.setWidth(3);    // 設置線寬
    pen.setColor(Qt::blue);
    pen.setStyle(Qt::SolidLine);   // 線的樣式
    pen.setCapStyle(Qt::FlatCap);        // 線條的端點樣式
    pen.setJoinStyle(Qt::BevelJoin);     // 連接點的樣式
    painter.setPen(pen);              // 設置QPainter的pen屬性

    // brush屬性
    QBrush brush;
    brush.setColor(Qt::green);        // 填充顏色
    brush.setStyle(Qt::SolidPattern);   // 填充樣式
    painter.setBrush(brush);

    // 繪圖
    painter.drawRect(rect);

    // 繪製直線
    pen.setColor(Qt::red);
    pen.setCapStyle(Qt::FlatCap);
    pen.setJoinStyle(Qt::BevelJoin);
    painter.setPen(pen);
    painter.drawLine(QPoint(5, 5), QPoint(width-10, height-10));
}

繪圖結果:

關於繪製圖像中的抗鋸齒,可以參考博客:https://blog.csdn.net/xiezhongyuan07/article/details/97116491

同時,可以擦除矩形中填充的顏色,以及重新填充:

painter.eraseRect(rect);   // 擦除矩形區域的內容
// 可以重新填充矩形區域
brush.setColor(Qt::black);
painter.fillRect(rect, brush);


QPainter的三個屬性介紹:

1. QPen的屬性:

Qpen主要用於在繪圖時對線條進行控制,包括線寬,顏色,線型的。

QPen主要的接口函數有:

更改器:(設置屬性)

1.pen.setColor(Qt::red);                        設置顏色
2.pen.setCapStyle(Qt::FlatCap);           設置端點樣式
3. pen.setJoinStyle(Qt::BevelJoin);       設置連接樣式

4. pen.setWidth()                                  設置寬度

5. pen.setStyle()                                   設置樣式

訪問器:(獲取屬性)

1.pen.color(Qt::red);                             獲取pen的顏色
2.pen.capStyle(Qt::FlatCap);                       獲取端點樣式
3. pen.joinStyle(Qt::BevelJoin);           連接樣式

4. pen.width()                                       寬度

5. pen.style()                                   樣式

線條樣式主要有六種:
1. SolidLine

2. DashLine

3. DotLine

4. DashDotLine

5. DashDotDotLine

6. CustomDashLine

7.NoPen

端點樣式有三種:

1. SquareCap

2. FlatCap

3. RoundCap

連接樣式也有三種:

1. BevelJoin

2. MiterJoin

3. RoundJoin

2. QBrush介紹:

QBrush定義了QPainter繪圖時的填充性能,包括顏色,填充樣式,填充材質。

QBrush的主要函數有以下幾種:
void    setColor ( Qt::GlobalColor color )
void    setStyle ( Qt::BrushStyle style )
void    setTexture ( const QPixmap & pixmap )
void    setTextureImage ( const QImage & image )

填充樣式setStyle()的參數是一個枚舉類型,主要有以下幾種:

例如,用幾種不同的方式填充矩形區域:

void Widget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);    // this代表Widget,及繪圖設備
    painter.setRenderHint(QPainter::Antialiasing);    // 繪畫普通圖形啓用反走樣, 即開啓抗鋸齒
    painter.setRenderHint(QPainter::TextAntialiasing);    // 繪畫文字反走樣, 即開啓抗鋸齒
    int width = this->width();      // 獲取繪圖區域的大小
    int height = this->height();

    QRect rect(width/4, height/4, width/2, height/2);   // 中間區域矩形框

    // brush屬性
    QBrush brush;
    brush.setColor(Qt::red);        // 填充顏色
    // brush.setStyle(Qt::SolidPattern);   // 填充樣式
    // brush.setStyle(Qt::Dense7Pattern);
    // brush.setStyle(Qt::CrossPattern);
    brush.setStyle(Qt::FDiagPattern);
    painter.setBrush(brush);

    // 繪圖
    painter.drawRect(rect);

}


QBrush填充漸變顏色:

Qt中有三種漸變的效果,如下圖所示:

1. QLinearGradient

        線性漸變顏色,可以指定一個起點顏色,終點顏色,還可以指定中間顏色,起點和終點之間可以進行插值計算,得到線性漸變的填充顏色。

void Widget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);    // this代表Widget,及繪圖設備
    painter.setRenderHint(QPainter::Antialiasing);    // 繪畫普通圖形啓用反走樣, 即開啓抗鋸齒
    painter.setRenderHint(QPainter::TextAntialiasing);    // 繪畫文字反走樣, 即開啓抗鋸齒
    int width = this->width();      // 獲取繪圖區域的大小
    int height = this->height();

    QRect rect(width/4, height/4, width/2, height/2);   // 中間區域矩形框

    QLinearGradient linearGrident(width/4, height/4, width/2, height/2);    // 指定漸變區域
    linearGrident.setColorAt(0, Qt::red);
    linearGrident.setColorAt(0.5, Qt::yellow);
    linearGrident.setColorAt(1, Qt::blue);
    // brush屬性
    QBrush brush;
    painter.setBrush(linearGrident);

    // 繪圖
    painter.drawRect(rect);

}

填充效果:

2.QConicalGradient: 圓錐形漸變,即圍繞一箇中心點逆時針生成漸變顏色。

void Widget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);    // this代表Widget,及繪圖設備
    painter.setRenderHint(QPainter::Antialiasing);    // 繪畫普通圖形啓用反走樣, 即開啓抗鋸齒
    painter.setRenderHint(QPainter::TextAntialiasing);    // 繪畫文字反走樣, 即開啓抗鋸齒
    int width = this->width();      // 獲取繪圖區域的大小
    int height = this->height();

    QConicalGradient gradient(width/2, height/2, 0);    // 填充參數參數cx, cy, start_angle,
    gradient.setColorAt(0, Qt::red);                    // 起始角度的位置,與線性漸變一樣,也是採用相對位置
    gradient.setColorAt(0.4, Qt::green);
    gradient.setColorAt(0.6, Qt::yellow);
    gradient.setColorAt(1, Qt::black);
    painter.setBrush(gradient);
    painter.drawRect(this->rect());  // 畫圓的區域

}

填充效果:

3. QRadialGradient: 輻射漸變填充,有簡單輻射漸變和擴展輻射漸變兩種方式,簡單輻射漸變是在一個圓內一個焦點和一個端點之間生成漸變顏色,擴展輻射漸變是在一個焦點圓和一箇中心圓之間生成漸變顏色。

void Widget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);    // this代表Widget,及繪圖設備
    painter.setRenderHint(QPainter::Antialiasing);    // 繪畫普通圖形啓用反走樣, 即開啓抗鋸齒
    painter.setRenderHint(QPainter::TextAntialiasing);    // 繪畫文字反走樣, 即開啓抗鋸齒
    int width = this->width();      // 獲取繪圖區域的大小
    int height = this->height();

    // 徑向漸變 c_x, c_y, radius, fx, fy 其中fx,fy爲焦點
    // c_x, c_y是輻射的中心點,radius是輻射半徑
    QRadialGradient gradient(width/2, height/2, qMax(width/4, height/4), width/2, height/2);    // 徑向漸變
    gradient.setColorAt(0, Qt::red);
    gradient.setColorAt(1, Qt::black);                  // 這裏使用的是邏輯座標 0開始位置 1結束位置
    // gradient.setSpread(QGradient::PadSpread);       // 設置漸變區域之外的漸變方式,即延展方式
    // gradient.setSpread(QGradient::RepeatSpread);
    gradient.setSpread(QGradient::ReflectSpread);
    painter.setBrush(gradient);
    painter.drawRect(this->rect());  // 畫圓的區域

}

同時,QRadialGradient需要通過setSpread()函數設置延展方式,也就是填充區域意外的填充方式,共有三種方式:

下面是填充的效果:

PadSpread:

RepeatSpread:

ReflectSpread:

QPainter繪製基本圖形元件:

QPainter可以繪製包括點,直線,曲線,矩形,圓弧等各種基本線條。具體的函數以及參數可以參考Qt文檔:(文檔部分)

座標系統和座標變換:

QPainter在窗口上繪圖的默認座標是繪圖設備的物理座標,爲了繪圖方便,QPainter提供了一些座標變換功能,通過平移,旋轉等座標變換,得到一個邏輯座標系統,使用邏輯座標系統在某些時候繪圖會更加方便。

常用的座標變換:
1. 平移變換:
void translate(dx, dy):表示將座標系統的原點移動到(dx, dy)位置。移動的單位爲像素。

2. 座標旋轉:

void rotate(angle): 將座標系統繞座標原點旋轉指定的角度。angle>0表示順勢正旋轉,angle<0表示逆時針旋轉。

3.縮放:

void scale(sx, sy): 表示縮放,sx,sy表示沿着x,y軸的縮放比例。參數大於1表示放大,參數小於1表示縮小。

4. 狀態保存於恢復:
在進行座標變換的時候,QPainter內部會有一個座標變換的矩陣,用save()函數保存座標的狀態。用restore()表示恢復保存的座標狀態。這兩個函數必須配對使用。resetTransform表示復位所有的變換操作。

 例子:

void Widget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);    // this代表Widget,及繪圖設備
    painter.setRenderHint(QPainter::Antialiasing);    // 繪畫普通圖形啓用反走樣, 即開啓抗鋸齒
    painter.setRenderHint(QPainter::TextAntialiasing);    // 繪畫文字反走樣, 即開啓抗鋸齒
    int width = this->width();      // 獲取繪圖區域的大小
    int height = this->height();

    // 生成五角星的五個頂點座標
    int radius = 100;      // 半徑
    const double Pi = 3.1415926;
    double deg = 360.0 / 5 * Pi / 180.0;
    QPoint points[5] = {
        QPoint(radius, 0),
        QPoint(radius * cos(deg), radius * sin(deg)),
        QPoint(radius * cos(2*deg), radius * sin(2*deg)),
        QPoint(radius * cos(3*deg), radius * sin(3*deg)),
        QPoint(radius * cos(4*deg), radius * sin(4*deg))
    };

    // 設置字體
    QFont font;
    font.setPointSize(12);
    font.setBold(true);
    painter.setFont(font);

    // 設置畫筆
    QPen pen;
    pen.setWidth(2);       // 設置線寬
    pen.setColor(Qt::blue);     // 設置顏色
    pen.setStyle(Qt::SolidLine);    // 設置線型
    pen.setCapStyle(Qt::FlatCap);
    pen.setJoinStyle(Qt::BevelJoin);
    painter.setPen(pen);

    // 設置畫刷
    QBrush brush;
    brush.setColor(Qt::red);
    brush.setStyle(Qt::SolidPattern);
    painter.setBrush(brush);

    // painter_path, 可以重複使用
    QPainterPath path;
    path.moveTo(points[0]);   // 起始點
    path.lineTo(points[2]);
    path.lineTo(points[4]);
    path.lineTo(points[1]);
    path.lineTo(points[3]);
    path.closeSubpath();     // 閉合路徑,相當於 path.lineTo(points[0]);
    // 添加文本
    path.addText(points[0], font, "1");
    path.addText(points[1], font, "2");
    path.addText(points[2], font, "3");
    path.addText(points[3], font, "4");
    path.addText(points[4], font, "5");

    // 保存座標狀態
    painter.save();
    painter.translate(width/4, height/4);    // 平移
    painter.drawPath(path);

    //  恢復座標
    painter.restore();
    painter.translate(width/2, height/2);    // 平移
    painter.scale(0.6, 0.6);        // 縮放,縮小操作
    painter.rotate(30);             // 旋轉
    painter.drawPath(path);         // 這裏的path重複利用了

}

繪製效果圖:

QPainterPath可以記錄幾個點的連線過程,可以對繪製複雜圖像的過程進行記錄,便於重複使用。

 

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