1. 绘制网格线、边框

paintWidget中绘制网格线,将其划分成一个个的100*100的区域

来到paintwidget.cpp文件,修改paintEvent()函数,如下:

void PaintWidget::paintEvent(QPaintEvent *event)
{
    // 创建画家类的对象,参数为绘图设备。指定为this,表示在当前窗口绘制
    QPainter painter(this);

    // 绘制网格线
    int w = width();
    int h = height();
    painter.setPen(QPen(QColor(180, 180, 180)));
    for (int x = 0; x < w; x += 100) {
        painter.drawLine(x, 0, x, h);  // 竖线
    }
    for (int y = 0; y < h; y += 100) {
        painter.drawLine(0, y, w, y);  // 横线
    }

    // 绘制最外侧的矩形边框
    // 需要放在绘制图形之后,否则矩形边框会被上边的图形覆盖
    painter.setRenderHint(QPainter::Antialiasing, false);
    painter.setPen(QColor(0, 0, 0));
    painter.setBrush(Qt::NoBrush);
    // painter.drawRect(QRect(0, 0, w, h));
    painter.drawRect(QRect(0, 0, w - 1, h - 1));
}

此时,运行效果:
image-20260813104851690

2. 绘制各种形状

在左上角100*100的范围内,绘制所有的14种图形

首先,来到paintwidget.cpp中,修改paintEvent()函数,如下:

void PaintWidget::paintEvent(QPaintEvent *event)
{
    // 1. 定义变量
    // 用于绘制点、线、多段线、多边形
    QPoint points[4] = {QPoint(10, 80), QPoint(20, 10), QPoint(80, 30), QPoint(90, 70)};

    // 用于绘制矩形、圆角矩形、圆、椭圆、圆弧、饼图、弦图、文本
    // QRect(int left, int top, int width, int height)
    QRect rect(10, 10, 80, 80);

    // 用于绘制路径/贝瑟尔曲线
    QPainterPath path;
    path.moveTo(0, 50);
    path.cubicTo(50, 0, 50, 100, 100, 50);  // 在当前点和结束点之间绘制贝瑟尔曲线

    // 用于绘制圆弧、饼图、弦图
    int startAngle = 30 * 16;
    int arcLength = 120 * 16;

    // 创建画家类的对象,参数为绘图设备。指定为this,表示在当前窗口绘制
    QPainter painter(this);

    // 2. 绘制网格线
    // ...

    // 3. 绘制所有图形
    switch (shape) {
        case 0:  // 点
            painter.drawPoints(points, 4);
            break;
        case 1:  // 线
            painter.drawLine(points[0], points[2]);
            break;
        case 2:  // 多段线
            painter.drawPolyline(points, 4);
            break;
        case 3:  // 多边形
            painter.drawPolygon(points, 4);
            break;
        case 4:  // 矩形
            painter.drawRect(rect);
            break;
        case 5:  // 圆角矩形
            // 第四个参数是一个枚举类型,可指定为:AbsoluteSize 或 RelativeSize
            // 当指定为AbsoluteSize,则2,3参数为圆角大小
            // 当指定为RelativeSize,则2,3参数为圆角百分比
            painter.drawRoundedRect(rect, 25, 25, Qt::RelativeSize);
            break;
        case 6:  // 圆
            painter.drawEllipse(rect);
            break;
        case 7:  // 椭圆
            rect.setRect(10, 20, 80, 60);
            painter.drawEllipse(rect);
            break;
        case 8:  // 圆弧
            // painter.drawRect(rect);
            painter.drawArc(rect, startAngle, arcLength);
            break;
        case 9:  // 饼图
            painter.drawPie(rect, startAngle, arcLength);
            break;
        case 10:  // 弦图
            painter.drawChord(rect, startAngle, arcLength);
            break;
        case 11:  // 路径/贝瑟尔曲线
            painter.drawPath(path);
            break;
        case 12:  // 文本
            painter.drawText(rect, Qt::AlignCenter, "B站n明王讲Qt");
            break;
        case 13:  // 图片
            painter.drawPixmap(10, 10, QPixmap(":/images/qt-logo.png"));
            break;
    }

    // 4.  绘制最外侧的矩形边框
    // ...
}

此时运行,由于shape默认值为0,会在100*100的位置绘制4个点。

然后,来到paintwidget.cpp中,修改setShape()函数,如下:

void PaintWidget::setShape(int shape)
{
    this->shape = shape;
    update();
}

由于在widget.cpp中为btnGroup绑定了信号槽,因此当点击对应的形状时,会调用这里的setShape()函数
update()函数的调用,会自动触发paintEvent()函数的调用,从而绘制相应的形状。