Qt:玩转QPainter序列七

前言

本章源码主要就是各种函数画各种图形。

正文

1. drawRects 系列函数 绘制矩形

  • void drawRects(const QRectF *rects, int rectCount);

    • 使用 QRectF 数组绘制 rectCount 个矩形。
  • inline void drawRects(const QVector<QRectF> &rectangles);

    • 使用 QVector<QRectF> 对象绘制多个矩形。
  • void drawRects(const QRect *rects, int rectCount);

    • 使用 QRect 数组绘制 rectCount 个矩形。
  • inline void drawRects(const QVector<QRect> &rectangles);

    • 使用 QVector<QRect> 对象绘制多个矩形。

示例

cpp 复制代码
void PaintWidget::paintEvent(QPaintEvent* event)
{
    Q_UNUSED(event);

    QPainter painter(this);
    //设置抗锯齿
    painter.setRenderHint(QPainter::Antialiasing,true);
    //设置粗一点
    QPen pen;
    pen.setWidth(3);
    painter.setPen(pen);
    QRect rects[] =  {
        //矩形左上角位于(0,0),宽30,高40
        QRect(10,10,30,40),
        QRect(50,10,30,40),
        QRect(90,10,30,40)
    };
    int rectsCount = sizeof(rects) / sizeof(rects[0]);
    painter.drawRects(rects,rectsCount);

    QVector<QRect> vrects;
    vrects<< QRect(10,60,30,40)
          << QRect(50,60,30,40)
          << QRect(90,60,30,40);
    pen.setColor(Qt::green);
    painter.setPen(pen);
    painter.drawRects(vrects);
}

2. drawEllipse 系列函数 绘制椭圆

  • void drawEllipse(const QRectF &r);

    • 在给定的 QRectF 边界内绘制椭圆。
  • void drawEllipse(const QRect &r);

    • 在给定的 QRect 边界内绘制椭圆。
  • inline void drawEllipse(int x, int y, int w, int h);

    • 在指定的 (x, y) 坐标和宽度、高度为 wh 的矩形内绘制椭圆。
  • inline void drawEllipse(const QPointF &center, qreal rx, qreal ry);

    • 在指定的 QPointF 中心绘制半径为 rxry 的椭圆。
  • inline void drawEllipse(const QPoint &center, int rx, int ry);

    • 在指定的 QPoint 中心绘制半径为 rxry 的椭圆。

示例

cpp 复制代码
void PaintWidget::paintEvent(QPaintEvent* event)
{
    Q_UNUSED(event);

    QPainter painter(this);
    //设置抗锯齿
    painter.setRenderHint(QPainter::Antialiasing,true);
    //设置粗一点
    QPen pen;
    pen.setWidth(3);
    painter.setPen(pen);
    QRect rect(30,40,50,50),rect2(80,10,30,40);
    //在rect内画一个椭圆,如rect为正方形,则画圆
    painter.drawEllipse(rect);
    painter.drawEllipse(rect2);

    //若rx = ry则画圆,否则为椭圆
    pen.setColor(Qt::gray);
    painter.setPen(pen);
    QPoint point(100,100);
    painter.drawEllipse(point,30,30);
    painter.drawEllipse(point,60,50);
}

3. drawPolyline 系列函数 绘制折线

使用绘制折线,系统不会将你首尾两个点相连,当然可以自己添加一个点使得首尾相连

  • void drawPolyline(const QPointF *points, int pointCount);

    • 使用 QPointF 数组绘制 pointCount 个点连接成的折线。
  • inline void drawPolyline(const QPolygonF &polyline);

    • 使用 QPolygonF 对象绘制折线。
  • void drawPolyline(const QPoint *points, int pointCount);

    • 使用 QPoint 数组绘制 pointCount 个点连接成的折线。
  • inline void drawPolyline(const QPolygon &polygon);

    • 使用 QPolygon 对象绘制折线。

示例

cpp 复制代码
void PaintWidget::paintEvent(QPaintEvent* event)
{
    Q_UNUSED(event);

    QPainter painter(this);
    //设置抗锯齿
    painter.setRenderHint(QPainter::Antialiasing,true);
    //设置粗一点
    QPen pen;
    pen.setWidth(3);
    painter.setPen(pen);
    QPoint points[] = {
        QPoint(10,10),
        QPoint(35,80),
        QPoint(65,24),
        QPoint(10,10)
    };
    int pointsCount = sizeof(points) / sizeof(points[0]);
    //使用首尾相同的点会形成闭合的图形
    painter.drawPolyline(points,pointsCount);

    QPolygon polygon;
    polygon << QPoint(80,80)
            << QPoint(100,20)
            << QPoint(40,90);
    pen.setColor(Qt::green);
    painter.setPen(pen);
    painter.drawPolyline(polygon);

}

4. drawPolygon 系列函数 绘制多边形

使用绘制多边形,系统会将你首尾两个点相连

  • void drawPolygon(const QPointF *points, int pointCount, Qt::FillRule fillRule = Qt::OddEvenFill);

    • 使用 QPointF 数组绘制多边形。fillRule 参数决定填充规则(例如 OddEvenFillWindingFill)。
  • inline void drawPolygon(const QPolygonF &polygon, Qt::FillRule fillRule = Qt::OddEvenFill);

    • 使用 QPolygonF 对象绘制多边形,fillRule 指定填充规则。
  • void drawPolygon(const QPoint *points, int pointCount, Qt::FillRule fillRule = Qt::OddEvenFill);

    • 使用 QPoint 数组绘制多边形,fillRule 指定填充规则。
  • inline void drawPolygon(const QPolygon &polygon, Qt::FillRule fillRule = Qt::OddEvenFill);

    • 使用 QPolygon 对象绘制多边形,fillRule 指定填充规则。

这里Qt::FillRule只有两种规则OddEvenFillWindingFillOddEvenFill是默认填充规则。它们的区别主要体现在如何确定一个点是否在多边形的内部。

1. OddEvenFill 填充规则

OddEvenFill 是一种简单的填充规则,通常用于确定一个点是否在多边形内部。判断方式如下:

  • 规则:从要检测的点向任意方向绘制一条直线,统计这条直线与多边形边界的交点数。如果交点数为奇数,则认为该点在多边形内部;如果为偶数,则认为该点在多边形外部。

示例

考虑一个八字形的多边形。如果一条直线穿过多边形的边界的次数是奇数,那么它内部的区域将会被填充。假设有两个重叠的区域,中间的重叠部分因为交点数为偶数,所以不会被填充。

2. WindingFill 填充规则

WindingFill 是另一种更复杂的填充规则,考虑了多边形边界的方向。判断方式如下:

  • 规则:从要检测的点向任意方向绘制一条直线,计算直线与多边形边界交点的环绕数(即"绕数")。当绕数为非零时,认为该点在多边形内部;为零时,该点在多边形外部。绕数通过多边形边界的方向(顺时针或逆时针)来计算。

计算绕数

  • 如果从点出发的直线与多边形的边从左向右相交,则绕数加1;
  • 如果从右向左相交,则绕数减1;
  • 经过所有交点之后,如果绕数不为0,则点在多边形内部。

示例

如果同样是八字形的多边形,由于考虑了绕数,重叠区域内的所有点都将被填充,因为这些点的绕数非零。

  • OddEvenFill:通过交点的奇偶性判断点是否在多边形内部,适合简单的形状。
  • WindingFill:通过计算绕数判断点是否在多边形内部,适合复杂的、多环绕的形状。

示例

cpp 复制代码
void PaintWidget::paintEvent(QPaintEvent* event)
{
    Q_UNUSED(event);

    QPainter painter(this);
    //设置抗锯齿
    painter.setRenderHint(QPainter::Antialiasing,true);
    //设置粗一点
    QPen pen;
    pen.setWidth(3);
    painter.setPen(pen);

    // 定义一个复杂的多边形形状
    QPolygon polygon;
    polygon << QPoint(50, 150) << QPoint(150, 50) << QPoint(250, 150)
            << QPoint(150, 250) << QPoint(100, 100) << QPoint(200, 100);

    // 使用 Qt::OddEvenFill 填充规则绘制多边形
    painter.setBrush(Qt::red);
    painter.drawPolygon(polygon, Qt::OddEvenFill);

    // 在另一个位置使用 Qt::WindingFill 填充规则绘制相同的多边形
    painter.translate(300, 0);
    painter.setBrush(Qt::blue);
    painter.drawPolygon(polygon, Qt::WindingFill);

}

5. drawConvexPolygon 系列函数 绘制凸多边形

凸多边形(凸多边形的所有内部角小于 180°)。

  • void drawConvexPolygon(const QPointF *points, int pointCount);

    • 使用 QPointF 数组绘制凸多边形。
  • inline void drawConvexPolygon(const QPolygonF &polygon);

    • 使用 QPolygonF 对象绘制凸多边形。
  • void drawConvexPolygon(const QPoint *points, int pointCount);

    • 使用 QPoint 数组绘制凸多边形。
  • inline void drawConvexPolygon(const QPolygon &polygon);

    • 使用 QPolygon 对象绘制凸多边形。

示例

cpp 复制代码
void PaintWidget::paintEvent(QPaintEvent* event)
{
    Q_UNUSED(event);

    QPainter painter(this);
    //设置抗锯齿
    painter.setRenderHint(QPainter::Antialiasing,true);
    //设置粗一点
    QPen pen;
    pen.setWidth(3);
    painter.setPen(pen);

    // 定义一个凸多边形形状,使用 QPoint 数组
    QPoint points1[] = {
        QPoint(50, 100),
        QPoint(150, 50),
        QPoint(250, 100),
        QPoint(200, 200),
        QPoint(100, 200)
    };
    int pointCount1 = sizeof(points1) / sizeof(points1[0]);

    // 使用 QPoint 数组绘制凸多边形
    painter.setBrush(Qt::green);
    painter.drawConvexPolygon(points1, pointCount1);

    // 定义一个凸多边形形状,使用 QPolygon 对象
    QPolygon polygon;
    polygon << QPoint(350, 100) << QPoint(450, 50) << QPoint(550, 100)
            << QPoint(500, 200) << QPoint(400, 200);

    // 使用 QPolygon 对象绘制凸多边形
    painter.setBrush(Qt::yellow);
    painter.drawConvexPolygon(polygon);
}

6. drawArc 系列函数 绘制弧线。

  • void drawArc(const QRectF &rect, int a, int alen);

    • 在指定的 QRectF 边界内绘制弧线,从角度 a 开始,弧长为 alen
  • inline void drawArc(const QRect &, int a, int alen);

    • 在指定的 QRect 边界内绘制弧线。
  • inline void drawArc(int x, int y, int w, int h, int a, int alen);

    • 在指定的矩形边界 (x, y, w, h) 内绘制弧线。

下面是一个使用 QPainterdrawArc 函数绘制弧线的示例,并讨论绘制弧线时的一些注意事项。

示例代码

cpp 复制代码
#include <QApplication>
#include <QWidget>
#include <QPainter>

class ArcWidget : public QWidget
{
protected:
    void paintEvent(QPaintEvent *event) override
    {
        QPainter painter(this);

        // 设置画笔和画刷
        QPen pen(Qt::blue, 2);
        painter.setPen(pen);

        // 定义矩形区域用于绘制弧线
        QRect rect(50, 50, 200, 200);

        // 设置弧线的起始角度和弧长(16分之一度)
        int startAngle = 30 * 16; // 30度
        int spanAngle = 120 * 16; // 120度

        // 绘制弧线
        painter.drawArc(rect, startAngle, spanAngle);
    }
};

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    ArcWidget window;
    window.resize(300, 300);
    window.show();

    return app.exec();
}
注意事项
  1. 角度表示方法:

    • drawArc 中,角度是以16分之一度为单位的。例如,30度对应的值为 30 * 16,完整的一圈(360度)对应的值为 360 * 16 = 5760
    • 起始角度 a 是相对于水平轴的角度,正值表示顺时针方向,负值表示逆时针方向。 起始角度可以任意选择,但常见的起点是0度(水平右侧)。
  2. 弧长选择:

    • alen 是弧的跨度,表示弧线从起始角度向顺时针方向的延展长度,也以16分之一度为单位。
    • 如果 alen 为正,弧线将顺时针绘制;如果为负,则逆时针绘制。
    • 弧长通常取决于所需的弧的大小,例如 90 * 16(90度)用于绘制1/4圆,180 * 16(180度)用于绘制半圆。

示例

cpp 复制代码
void PaintWidget::paintEvent(QPaintEvent* event)
{
    Q_UNUSED(event);

    QPainter painter(this);
    //设置抗锯齿
    painter.setRenderHint(QPainter::Antialiasing,true);
    //设置粗一点
    QPen pen;
    pen.setWidth(3);
    painter.setPen(pen);

    // 定义矩形区域用于绘制弧线
    QRect rect(50, 50, 200, 200);

    // 设置弧线的起始角度和弧长(16分之一度)
    int startAngle = 30 * 16; // 30度
    int spanAngle = 120 * 16; // 120度

    // 绘制弧线
    painter.drawArc(rect, startAngle, spanAngle);
}

7. drawPie 系列函数 绘制饼形

这些函数用于绘制饼形。

  • void drawPie(const QRectF &rect, int a, int alen);

    • 在指定的 QRectF 边界内绘制饼形,从角度 a 开始,饼形弧长为 alen
  • inline void drawPie(int x, int y, int w, int h, int a, int alen);

    • 在指定的矩形边界 (x, y, w, h) 内绘制饼形。
  • inline void drawPie(const QRect &, int a, int alen);

    • 在指定的 QRect 边界内绘制饼形。

示例

cpp 复制代码
void PaintWidget::paintEvent(QPaintEvent* event)
{
    Q_UNUSED(event);

    QPainter painter(this);
    //设置抗锯齿
    painter.setRenderHint(QPainter::Antialiasing,true);
    //设置粗一点
    QPen pen;
    pen.setWidth(3);
    painter.setPen(pen);

    // 定义矩形区域用于绘制弧线
    QRect rect(50, 50, 200, 200);

    // 设置弧线的起始角度和弧长(16分之一度)
    int startAngle = 30 * 16; // 30度
    int spanAngle = 120 * 16; // 120度
    painter.setBrush(Qt::green);
    // 绘制饼形
    painter.drawPie(rect, startAngle, spanAngle);
}

8. drawChord 系列函数 绘制弦

弦(由弧线和直线连接的部分)。

  • void drawChord(const QRectF &rect, int a, int alen);

    • 在指定的 QRectF 边界内绘制弦,从角度 a 开始,弧长为 alen
  • inline void drawChord(int x, int y, int w, int h, int a, int alen);

    • 在指定的矩形边界 (x, y, w, h) 内绘制弦。
  • inline void drawChord(const QRect &, int a, int alen);

    • 在指定的 QRect 边界内绘制弦。

示例

cpp 复制代码
void PaintWidget::paintEvent(QPaintEvent* event)
{
    Q_UNUSED(event);

    QPainter painter(this);
    //设置抗锯齿
    painter.setRenderHint(QPainter::Antialiasing,true);
    //设置粗一点
    QPen pen;
    pen.setWidth(3);
    painter.setPen(pen);

    // 定义矩形区域用于绘制弧线
    QRect rect(50, 50, 200, 200);

    // 设置弧线的起始角度和弧长(16分之一度)
    int startAngle = 30 * 16; // 30度
    int spanAngle = 120 * 16; // 120度
    painter.setBrush(Qt::green);
    // 绘制弦
    painter.drawChord(rect, startAngle, spanAngle);
}

9. drawRoundedRect 系列函数 绘制圆角矩形

  • void drawRoundedRect(const QRectF &rect, qreal xRadius, qreal yRadius, Qt::SizeMode mode = Qt::AbsoluteSize);

    • 在指定的 QRectF 边界内绘制圆角矩形,xRadiusyRadius 分别是水平和垂直方向的圆角半径。
  • inline void drawRoundedRect(int x, int y, int w, int h, qreal xRadius, qreal yRadius, Qt::SizeMode mode = Qt::AbsoluteSize);

    • 在指定的矩形边界 (x, y, w, h) 内绘制圆角矩形。
  • inline void drawRoundedRect(const QRect &rect, qreal xRadius, qreal yRadius, Qt::SizeMode mode = Qt::AbsoluteSize);

    • 在指定的 QRect 边界内绘制圆角矩形。

下面是使用 QPainterdrawRoundedRect 函数绘制带圆角矩形的示例,并讨论一些注意事项。

示例代码

cpp 复制代码
#include <QApplication>
#include <QWidget>
#include <QPainter>

class RoundedRectWidget : public QWidget
{
protected:
    void paintEvent(QPaintEvent *event) override
    {
        QPainter painter(this);

        // 设置画笔和画刷
        QPen pen(Qt::black, 2);
        painter.setPen(pen);
        painter.setBrush(QBrush(Qt::green, Qt::SolidPattern));

        // 定义矩形区域
        QRect rect(50, 50, 200, 100);

        // 设置圆角半径
        qreal xRadius = 20;
        qreal yRadius = 20;

        // 绘制圆角矩形
        painter.drawRoundedRect(rect, xRadius, yRadius, Qt::AbsoluteSize);
    }
};

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    RoundedRectWidget window;
    window.resize(300, 200);
    window.show();

    return app.exec();
}
注意事项
  1. 圆角半径 (xRadius, yRadius):

    • xRadiusyRadius 分别控制矩形的水平和垂直圆角半径。这两个值越大,圆角越圆润,矩形的边角越圆滑。
    • 如果 xRadiusyRadius 的值太大,可能会导致矩形的边角接近圆形,甚至使矩形的某些部分消失。
    • 选择合适的半径值以确保圆角矩形的视觉效果符合预期。
  2. 尺寸模式 (Qt::SizeMode):

    • Qt::AbsoluteSize:默认情况下,xRadiusyRadius 是以绝对像素为单位的,这也是最常用的模式。
    • Qt::RelativeSize:在这种模式下,xRadiusyRadius 是相对于矩形尺寸的比例。例如,xRadius = 0.1 表示圆角半径为矩形宽度的10%。
    • 根据需求选择合适的尺寸模式,通常使用 Qt::AbsoluteSize 以获得更精确的控制。

示例

cpp 复制代码
void PaintWidget::paintEvent(QPaintEvent* event)
{
    Q_UNUSED(event);

    QPainter painter(this);
    //设置抗锯齿
    painter.setRenderHint(QPainter::Antialiasing,true);
    //设置粗一点
    QPen pen;
    pen.setWidth(3);
    painter.setPen(pen);

    // 定义矩形区域
    QRect rect(50, 50, 200, 100);

    // 设置圆角半径
    qreal xRadius = 20;
    qreal yRadius = 20;

    // 绘制圆角矩形
    painter.drawRoundedRect(rect, xRadius, yRadius, Qt::AbsoluteSize);
    // 下移200个像素
    painter.translate(0,200);
    //这点不知道是什么问题,当将0.1,0.5调整到较大的数时,才有效果
    painter.drawRoundedRect(rect,0.1,0.5,Qt::RelativeSize);
}
相关推荐
小五Five几秒前
TypeScript项目中Axios的封装
开发语言·前端·javascript
前端每日三省2 分钟前
面试题-TS(八):什么是装饰器(decorators)?如何在 TypeScript 中使用它们?
开发语言·前端·javascript
凡人的AI工具箱16 分钟前
15分钟学 Go 第 60 天 :综合项目展示 - 构建微服务电商平台(完整示例25000字)
开发语言·后端·微服务·架构·golang
chnming198731 分钟前
STL关联式容器之map
开发语言·c++
进击的六角龙33 分钟前
深入浅出:使用Python调用API实现智能天气预报
开发语言·python
檀越剑指大厂33 分钟前
【Python系列】浅析 Python 中的字典更新与应用场景
开发语言·python
湫ccc41 分钟前
Python简介以及解释器安装(保姆级教学)
开发语言·python
程序伍六七1 小时前
day16
开发语言·c++
wkj0011 小时前
php操作redis
开发语言·redis·php
极客代码1 小时前
【Python TensorFlow】进阶指南(续篇三)
开发语言·人工智能·python·深度学习·tensorflow