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));
}

绘图结果:

C++ Qt学习笔记(4)绘图

关于绘制图像中的抗锯齿,可以参考博客:https://blog.csdn.net/xiezhongyuan07/article/details/97116491

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

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

C++ Qt学习笔记(4)绘图

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

C++ Qt学习笔记(4)绘图

端点样式有三种:

1. SquareCap

2. FlatCap

3. RoundCap

C++ Qt学习笔记(4)绘图

连接样式也有三种:

1. BevelJoin

2. MiterJoin

3. RoundJoin

C++ Qt学习笔记(4)绘图

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()的参数是一个枚举类型,主要有以下几种:

C++ Qt学习笔记(4)绘图

C++ Qt学习笔记(4)绘图

例如,用几种不同的方式填充矩形区域:

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);

}

C++ Qt学习笔记(4)绘图C++ Qt学习笔记(4)绘图C++ Qt学习笔记(4)绘图

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);

}

填充效果:
C++ Qt学习笔记(4)绘图

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());  // 画圆的区域

}

填充效果:

C++ Qt学习笔记(4)绘图

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()函数设置延展方式,也就是填充区域意外的填充方式,共有三种方式:

C++ Qt学习笔记(4)绘图

下面是填充的效果:

PadSpread:

C++ Qt学习笔记(4)绘图

RepeatSpread:

C++ Qt学习笔记(4)绘图

ReflectSpread:

C++ Qt学习笔记(4)绘图

QPainter绘制基本图形元件:

QPainter可以绘制包括点,直线,曲线,矩形,圆弧等各种基本线条。具体的函数以及参数可以参考Qt文档:(文档部分)

C++ Qt学习笔记(4)绘图

坐标系统和坐标变换:

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重复利用了

}

绘制效果图:
C++ Qt学习笔记(4)绘图

QPainterPath可以记录几个点的连线过程,可以对绘制复杂图像的过程进行记录,便于重复使用。

 

原文链接: https://www.cnblogs.com/ncepubye/p/12723998.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    C++ Qt学习笔记(4)绘图

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/396452

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年4月6日 上午11:20
下一篇 2023年4月6日 上午11:20

相关推荐