QPainter之绘制鼠标路径(画笔工具)

本文详细讲述了使用QPainter在Qt中通过事件重写实现动态绘图的过程,从记录鼠标移动坐标到转换为线和多边线,包括点阵、多边形和多边线的区别与应用。作者还分享了代码实例,展示了如何优化记录和绘制策略以获得流畅的线条效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


前言

绘制简单的直线、矩形、椭圆等就不介绍了,毕竟那种东西就一个函数就能解决的问题,无非就是一些抗锯齿之类的细节,大家自行百度相关函数即可。

提示:本篇直接讲绘任意图——画笔工具

一、事件重写

想要绘图,得知道落笔的位置,而这里不再教大家如何创建笔了,就拿基本QPen绘图。

bool event(QEvent *event) override;

为了方便,上面就写一个总事件函数。

二、记录坐标

1.定义成员,以记录坐标位置

QVector<QPoint> points;

为什么用QVector不用QList或者QPoint数组,看后面。

2.加入坐标

代码如下:

bool Widget::event(QEvent *event)
{
    QMouseEvent *e = static_cast<QMouseEvent*>(event);
    if(event->type()==QEvent::MouseMove){
        this->points.append(e->pos());
        this->update();
    }
    return QWidget::event(event);
}

就只是将·按住并移动·的坐标加入到数组中,没有任何别的代码。

3.绘画点数组

我们很容易想到下面这个函数,来将所有点画出来。
在这里插入图片描述
进入QPolygon中,我们可以看到有这样一个构造函数,参数为QVector<QPoint> &points来构建一个QPolygon
在这里插入图片描述
于是代码可以这样写:
(为了简洁,可以直接写在bool Widget::event(QEvent *event)函数中)

if(event->type()==QEvent::Paint){
    QPainter painter(this);
    QPen pen(QColor(255,0,0));
    pen.setWidth(3);
    painter.setPen(pen);
    
    painter.drawPoints(QPolygon(this->points));
}

鼠标稍微挪快,画出线的效果却是这样:(断断续续)
在这里插入图片描述
所以立刻想到画线,而非画点:

//于是注销掉画点的函数,加上下面这句
painter.drawLines(QPolygon(this->points));

效果如下:
在这里插入图片描述

我承认确实有点儿改观,但是这并非想象中的效果。

后来发现有这样一个函数:

painter.drawPolygon(QPolygon(this->points));

它是用来画多边形的,效果有我们想象中有偏差,不过却是很接近了,仔细看看,也就是鼠标按下的那个点与鼠标当前的点之间有一条连线,仅此而已。

在这里插入图片描述
这是因为画多边形,多边形是一个封闭图形,所以才这样设计,然而我们继续往下找,可以接着找到这样一个函数:

painter.drawPolyline(QPolygon(this->points));

画 “多边线” 这个函数完美的符合了我们的预期。

请添加图片描述
因为没有鼠标松开判断,所以认为两次画的线为同一条线,要改的画也简单,将QVector<QPoint>改为二维数组,并且在鼠标松开时,结束此条线的记录,并且重绘函数里也要遍历数组,一根线一根线的画。

还是写一下吧:

//.h文件中增加(或修改成)下面两行
QVector<QVector<QPoint>> points;
QVector<QPoint> point;
//.cpp文件中
bool Widget::event(QEvent *event)
{
    QMouseEvent *e = static_cast<QMouseEvent*>(event);

    if(event->type()==QEvent::MouseMove){
        this->point.append(e->pos());
        this->update();
    }
    else if(event->type()==QEvent::MouseButtonRelease){
        points.append(point);
        point.clear();
    }
    if(event->type()==QEvent::Paint){
        QPainter painter(this);
        QPen pen(QColor(255,0,0));
        pen.setWidth(3);
        painter.setPen(pen);
        painter.drawPolyline(QPolygon(point));
        for(auto p:this->points){
            painter.drawPolyline(QPolygon(p));
        }
    }
    return QWidget::event(event);
}

效果如下:

在这里插入图片描述
代码较少,就不传github了。
手打不易,转发请标注原文链接,谢谢。

感谢各位的阅读。

下一篇:QPainter实现简单的绘图程序(绘图工具)

<think>我们正在讨论在Qt框架中绘制曲线路径Qt提供了强大的绘图功能,主要通过QPainterPath类来创建和绘制复杂的路径,包括直线和曲线。 曲线部分可以使用二次贝塞尔曲线(quadTo)或三次贝塞尔曲线(cubicTo)来绘制。 步骤: 1. 创建一个QPainterPath对象。 2. 使用moveTo将路径起点移动到指定位置。 3. 使用quadTo或cubicTo添加曲线段。 4. 在绘图事件(paintEvent)中使用QPainter绘制这个路径。 示例代码: 假设我们要绘制一个从点(100,100)开始,到点(200,200)结束的二次贝塞尔曲线,控制点为(150,50)。 注意:二次贝塞尔曲线有一个控制点,而三次贝塞尔曲线有两个控制点。 下面是一个简单的示例,展示如何在自定义的QWidget中绘制曲线路径。</think>在Qt框架中实现曲线路径绘制,主要使用`QPainterPath`类结合贝塞尔曲线函数。以下是详细实现方案: ### 核心实现步骤 1. **创建路径对象** ```cpp QPainterPath path; path.moveTo(startPoint); // 设置起点 ``` 2. **添加曲线段** - **二次贝塞尔曲线**(单控制点) ```cpp path.quadTo(controlPoint, endPoint); // 控制点 + 终点 ``` - **三次贝塞尔曲线**(双控制点) ```cpp path.cubicTo(ctrlPoint1, ctrlPoint2, endPoint); // 控制点1 + 控制点2 + 终点 ``` 3. **绘制路径**(在`paintEvent`中) ```cpp void MyWidget::paintEvent(QPaintEvent*) { QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); // 抗锯齿 painter.setPen(QPen(Qt::blue, 2)); // 蓝色描边 painter.drawPath(path); // 绘制路径 } ``` ### 完整示例代码 ```cpp #include <QWidget> #include <QPainterPath> #include <QPainter> class CurveWidget : public QWidget { public: CurveWidget(QWidget *parent = nullptr) : QWidget(parent) { // 构建曲线路径 path.moveTo(50, 200); // 起点 path.cubicTo(150, 50, 250, 350, 350, 200); // 三次贝塞尔曲线 } protected: void paintEvent(QPaintEvent*) override { QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); // 绘制曲线 painter.setPen(QPen(Qt::red, 3)); painter.drawPath(path); } private: QPainterPath path; }; ``` ### 关键功能扩展 1. **动态编辑控制点** 存储控制点至`QVector<QPointF>`,通过鼠标事件更新控制点位置并重绘: ```cpp void mouseMoveEvent(QMouseEvent *e) override { if (m_dragging) { controlPoints[currentIndex] = e->pos(); update(); // 触发重绘 } } ``` 2. **路径平滑处理** 使用`QPainterPath::simplified()`自动简化路径: ```cpp QPainterPath smoothPath = originalPath.simplified(); ``` 3. **虚线效果** 自定义画笔样式: ```cpp QPen dashPen(Qt::black, 2, Qt::DashLine); painter.setPen(dashPen); ``` ### 性能优化建议 - 复杂路径启用`QPainter::Antialiasing`提升视觉质量 - 静态路径使用`QPicture`缓存绘图指令[^1] - 避免在`paintEvent`中构建路径对象 ### 应用场景 - 数据可视化中的趋势线绘制 - 矢量图形编辑器(如自定义形状) - 动画运动轨迹设计 - 地理信息系统中的路线渲染[^2] ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值