服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - Qt 实现画线笔锋效果详细原理及示例代码

Qt 实现画线笔锋效果详细原理及示例代码

2021-08-30 13:33luoyayun361 C/C++

这篇文章主要介绍了Qt 实现画线笔锋效果详细原理及示例代码。文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

前言

之前写过一篇文章介绍Qt中绘制平滑曲线的两种方式,文章在这里。这篇文章详细介绍了绘制的原理和实现方式,那么,如果要在此曲线上实现笔锋效果怎么做呢?

所谓的笔锋效果,就是钢笔书写抬笔时的笔尖,也就是说,绘制曲线抬笔时形成一个笔尖的效果。

话不多说,直接来看效果:

Qt 实现画线笔锋效果详细原理及示例代码

动画效果如下:

Qt 实现画线笔锋效果详细原理及示例代码

实现原理

要实现该效果,需要完成以下几个关键步骤:

1.每两个点形成一个贝塞尔曲线path进行绘制

2.最新的一条path绘制细线(笔锋最细处的宽度)

3.倒数第二条path绘制粗线(正常的线条宽度)

4.在两条path连接处补充点使其过渡平滑

接下来一步步的分析,首先第一条,每两个点形成一个贝塞尔曲线path进行绘制,这个比较简单,就不多讲了吧,也就是说,在move事件中,每来一个新点,就让该点和前一个点生成一个贝塞尔曲线,使用QPainterPath中的quadTo函数,之所以要用贝塞尔曲线,是为了解决折线问题,这个在前面的文章中已经介绍过了。这里就不重复说咯。

我们直接来看第二条: 最新的一个path绘制细线。

这个怎么理解呢?看一个图示:

Qt 实现画线笔锋效果详细原理及示例代码

以上是线条放大的效果,最新的path,也就是上面的newPath,通过当前点和前一个点生成的这条path,绘制一条细线,这条线就作为笔锋,假如这时候抬笔,那么newPath就是最后一条线段,那么笔锋就是这条线来形成的。

做完第二步,我们看一下绘制效果:

第三步:倒数第二条path绘制粗线(正常的线条宽度)
从上面的图示可以看到,我们将最新的newPath绘制细线,那么如果这时候又出现一个新的点,形成了新的path,而之前的newPath就会变成前一个path,这里命名为lastPath,由于该path还是细线,所以这里我们需要将前一个path重新补充绘制成正常的粗线,图示如下:

Qt 实现画线笔锋效果详细原理及示例代码

这里的黄线,也就是我们补充绘制的线条,而最新的path依然是细线,根据以上示意图就很容易明白了。

所以简单来说,就是不断的将最新path绘制成细线,然后将前一个path补充绘制成粗线。

看一下效果:

Qt 实现画线笔锋效果详细原理及示例代码

为了区分不同的path,这里采用了不同的颜色来代表,每一段颜色代表一个path,最新的path就是右边的绿色线条,可以看到最新的path和前一条path由于线宽不同, 所以连接处并不平滑,所以要解决这个问题,需要做最后一步:补点。

什么是补点,就是说我们需要在连接处 根据最新path的线条路径来绘制一系列的点进行填充,使其连接处看起来平滑,图示如下:

Qt 实现画线笔锋效果详细原理及示例代码

上面的圈圈就是补充的点,点与点之间距离越小,看起来就越平滑,而圈圈的圆心点是跟随最新的path线条走的,就是path线的线条高度的中心点,圈圈的半径大小逐渐变小。

再看看补充点后的效果:

Qt 实现画线笔锋效果详细原理及示例代码

可以看到,笔尖黑色的地方线条就是通过补充点来实现的。

那么,问题来了,如何知道最后这条path的路径呢?
其实Qt已经提供了接口,我们通过QPainterPath来生成的曲线,这个类提供了一个函数叫pointAtPercent,定义如下:

Qt 实现画线笔锋效果详细原理及示例代码

这个接口就是返回在path曲线上的坐标点,通过传入百分比来调用,很方便了吧。
我这里的补充点实现方式,就是通过循环的不断的绘制:

  1. //在两个path连接处绘制补充点,使其连接处平滑
  2. void WbCanvasItem::drawPatchPoint(QPainter * painter,QPainterPath path)
  3. {
  4. qreal temp = (PENWIDTH-3)/100.;
  5. int k = 0;
  6. for (qreal i = 0;i < 1; i+=0.01) {
  7. k++;
  8. painter->setPen(QPen(Qt::black,PENWIDTH-temp*k,
  9. Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
  10. painter->drawPoint(path.pointAtPercent(i));
  11. }
  12. }

前三步骤代码:

  1. QPainterPath lastPath = obj->StrokeLastPath(PENWIDTH);
  2. m_pRealPainter->fillPath(lastPath,Qt::red);//填充轮廓
  3. path = obj->StrokePath(3);
  4. m_pRealPainter->fillPath(path,Qt::red);//填充轮廓
  5. drawPatchPoint(m_pRealPainter,obj->path());

ok ,整个实现方式已介绍完成,本文主要讲解原理,代码未整理,就不上传了,用到的关键函数已经介绍过,只要明白原理过后,根据原理一步步的操作,就可以实现了。

Qt 实现钢笔画线效果详细原理

到此这篇关于Qt 实现画线笔锋效果详细原理及示例代码的文章就介绍到这了,更多相关Qt 画线笔锋效果内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/luoyayun361/article/details/104312253

延伸 · 阅读

精彩推荐
  • C/C++C语言实现双人五子棋游戏

    C语言实现双人五子棋游戏

    这篇文章主要为大家详细介绍了C语言实现双人五子棋游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    两片空白7312021-11-12
  • C/C++深入C++拷贝构造函数的总结详解

    深入C++拷贝构造函数的总结详解

    本篇文章是对C++中拷贝构造函数进行了总结与介绍。需要的朋友参考下...

    C++教程网5182020-11-30
  • C/C++c/c++实现获取域名的IP地址

    c/c++实现获取域名的IP地址

    本文给大家汇总介绍了使用c/c++实现获取域名的IP地址的几种方法以及这些方法的核心函数gethostbyname的详细用法,非常的实用,有需要的小伙伴可以参考下...

    C++教程网10262021-03-16
  • C/C++c/c++内存分配大小实例讲解

    c/c++内存分配大小实例讲解

    在本篇文章里小编给大家整理了一篇关于c/c++内存分配大小实例讲解内容,有需要的朋友们可以跟着学习参考下。...

    jihite5172022-02-22
  • C/C++使用C++制作简单的web服务器(续)

    使用C++制作简单的web服务器(续)

    本文承接上文《使用C++制作简单的web服务器》,把web服务器做的功能稍微强大些,主要增加的功能是从文件中读取网页并返回给客户端,而不是把网页代码...

    C++教程网5492021-02-22
  • C/C++C语言main函数的三种形式实例详解

    C语言main函数的三种形式实例详解

    这篇文章主要介绍了 C语言main函数的三种形式实例详解的相关资料,需要的朋友可以参考下...

    ieearth6912021-05-16
  • C/C++关于C语言中E-R图的详解

    关于C语言中E-R图的详解

    今天小编就为大家分享一篇关于关于C语言中E-R图的详解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看...

    Struggler095962021-07-12
  • C/C++OpenCV实现拼接图像的简单方法

    OpenCV实现拼接图像的简单方法

    这篇文章主要为大家详细介绍了OpenCV实现拼接图像的简单方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    iteye_183805102021-07-29