Qt 鼠标/触屏绘制平滑曲线(支持矢量/非矢量方式)

 更新时间:2020年04月08日 09:27:10   作者:luoyayun361  
这篇文章主要介绍了Qt 鼠标/触屏绘制平滑曲线(支持矢量/非矢量方式),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

前言

Qt通过鼠标或者触屏,实时绘制平滑曲线,通常有两种方式实现:矢量绘图和非矢量绘图,这两种画线方式从实现上有些不同,其原理也不太一样,稍后会做详细介绍。而鼠标或者触屏画线也不大一样,通常如果只实现鼠标画线的话,那么只需要重新实现鼠标事件即可(mousePressEvent、mouseMoveEvent、mouseReleaseEvent),而要在触控屏上画线,如果需要支持多点画线的话,就必须处理QTouchEvent事件才行,但是如果触屏上只支持单点画线,那也可以直接实现鼠标事件,因为第一个触点的事件会同时进入到QTouchEvent和Mouse事件中。QTouchEvent中可以区分出多点时每个触点的id,通过id进行区分每个点的数据。

通常情况下,为了提升绘图效率,要实现这种绘图的功能,都是用QGraphics体系来完成,因为QGraphics刷新机制和QWidget不太一样,它可以做区域刷新,这样能保证效率更高,特别是针对一些分辨率较高的设备,就很明显了。具体这两个体系间的区别就不在这里进行描述。

所以,接下来为了演示矢量和非矢量画图方式,我们在QGraphics体系中实现一个简单的画板程序。注重画线效率,保证线条平滑无折线,无锯齿,支持多点画线。

效果图

先开看看非矢量绘图的效果:

再看矢量绘图效果:

二者区别

通过上面的两个图对比,相信大家已经看出了一些区别。我们再详细介绍一下这两者的区别。

非矢量绘图

  • 优点:速度快。非矢量绘图原理是直接在一张图片上进行绘制,其渲染速度很快,即便是画了很多线条, 也不会有卡顿的效果,擦除时同样很快。
  • 缺点:缩放失真。由于非矢量绘图是在图片上渲染,当缩放图片时,会导致线条模糊不清晰,如果只是小范围的缩放还能接受,无限缩放的话就会很明显了。

矢量绘图

  • 优点:无限缩放,不失真。矢量绘图是将点数据绘制生成一个单独的对象,当进行缩放的时候,会重新进行渲染,所以矢量绘图的方式不会导致图像失真。
  • 缺点:线条多时会卡顿,擦除尤其明显。由于矢量绘图是生成一个单独的对象,所以当画线多的情况下,会触发所有有交集的对象进行刷新,擦除的时候,会去计算线条之间的交集并做删减,这个过程会很慢,并且会将整个对象item进行刷新,所以卡顿明显(上述效果图就可以看出来了)。

通过以上两者的优缺点对比,根据实际需要进行选择实际的画线模式。

解决实时绘图折线问题

折线效果:


可以看到上述画线有很明显的折线,线条不平滑。

通常绘制这种线条,第一反应想到的是讲两个点直接连接起来行成一条直线,但是,由于两点之间距离比较大,特别是触控屏,点与点之间并不是很密集,因为上层应用在主线程渲染的时候,系统会自动丢弃一些数据点,即便是底层上报的点很多,上层应用接收到的点也会减少,所以不能直接用连接两点的方式来实现。

那么,该怎么解决呢?
绘制贝塞尔曲线。

在move的过程中实时生成贝塞尔曲线path,这样就能保证线条无折线。QPainterPath支持贝塞尔曲线绘制,参加以下函数:

void QPainterPath::quadTo(const QPointF &c, const QPointF &endPoint)

Adds a quadratic Bezier curve between the current position and the given endPoint with the control point specified by c.
After the curve is added, the current point is updated to be at the end point of the curve.

注意该函数,第一个参数是控制点,该点就是上一个触控点,而第二个参数是前一个点和当前点的中点,也就是两个点坐标加起来除以2.

非矢量绘图实现方式

所谓的非矢量绘图,就是在一张图片上进行绘制,然后将图片渲染到QGraphicsItem的背景上面,前面我们已经提到,该方式渲染速度非常快,无论画多少线条都不会影响速度,而擦除功能只需要按照同样的方式绘制背景色即可。

但是该方式在缩放过后图片会有些模糊,如果只是小范围的缩放还好,无限缩放就需要用到矢量绘图的方式了。

矢量绘图实现方式

相比之下,矢量绘图就会稍微麻烦一点,所谓矢量绘图,就是将path曲线直接生成一个独立的对象,将该对象添加到scene中,这种模式下会有一个缺陷,就是当画线较多的情况下,刷新会比较慢,因为会导致整条曲线(只要有交集)刷新,从而导致卡顿的效果,并且在擦除时,需要实时计算擦除的path与实际线条path的交集,然后进行计算,减去擦除的path,这个过程是最耗时的,并且也会引发整个item刷新。前面写过文章介绍QGraphics体系的刷新机制,在这里

由于矢量绘图需要生成一条完整的path进行绘制,而触控点是在move事件中取到,如果实时生成贝塞尔曲线去绘制,那么当一直不松手的画一条线时,画到后面将会越来越慢,因为动态生成path后会重新将整条path进行渲染,随着线条越长,那么刷新区域就会越大,这就会导致刷新变慢而延迟变高。那么怎么解决这个问题呢?答案就是通过双缓冲的方式来实现绘制。

双缓冲绘图

上面介绍到,通过非矢量绘图的方式,速度会非常快,那么双缓冲绘图就是要结合非矢量来进行,其原理就是:在press事件中生成一条path,接着move中动态增加这条path,然后在临时层上进行非矢量绘图,这时候绘制的速度会非常快,最后在release事件中将完整的path绘制成矢量图,然后将临时层画线清空。基本原理就是这样。

双缓冲绘图方式,在绘制过程中是通过非矢量的方式在临时层进行,release后生成完整的矢量path,这种方式速度会非常快,并且直接绘制完整的一条path不会有锯齿。所以这是最佳选择。

代码太多,就不附代码了。

到此这篇关于Qt 鼠标/触屏绘制平滑曲线(支持矢量/非矢量方式)的文章就介绍到这了,更多相关Qt 绘制平滑曲线内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • linux c++ 服务器端开发面试必看书籍整理

    linux c++ 服务器端开发面试必看书籍整理

    这篇文章主要介绍了linux c++ 服务器端开发面试必看书籍整理,需要的朋友可以参考下
    2020-02-02
  • C++中箭头运算符的含义与用法讲解

    C++中箭头运算符的含义与用法讲解

    今天小编就为大家分享一篇关于C++中箭头运算符的含义与用法讲解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-04-04
  • C语言关键字总结解析

    C语言关键字总结解析

    这篇文章主要介绍了C语言关键字总结解析,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是本文的详细内容,需要的朋友可以参考下
    2021-07-07
  • 线段树详解以及C++实现代码

    线段树详解以及C++实现代码

    线段树在一些acm题目中经常见到,这种数据结构主要应用在计算几何和地理信息系统中,这篇文章主要给大家介绍了关于线段树以及C++实现的相关资料,需要的朋友可以参考下
    2021-07-07
  • C语言实现猜拳游戏

    C语言实现猜拳游戏

    这篇文章主要为大家详细介绍了C语言实现猜拳游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-02-02
  • C++基础入门教程(七):一些比较特别的基础语法总结

    C++基础入门教程(七):一些比较特别的基础语法总结

    这篇文章主要介绍了C++基础入门教程(七):一些比较特别的基础语法总结,本文总结的都是一些特殊的语法,需要的朋友可以参考下
    2014-11-11
  • C语言编程中生成随机数的入门教程

    C语言编程中生成随机数的入门教程

    这篇文章主要介绍了C语言编程中生成随机数的入门教程,包括利用rand()函数来编写随机数生成器的示例,要的朋友可以参考下
    2015-12-12
  • C/C++经典实例之模拟计算器示例代码

    C/C++经典实例之模拟计算器示例代码

    最近在看到的一个需求,本以为比较简单,但花了不少时间,所以下面这篇文章主要给大家介绍了关于C/C++经典实例之模拟计算器的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面来一起看看吧。
    2017-10-10
  • C语言中字符和字符串处理(ANSI字符和Unicode字符)

    C语言中字符和字符串处理(ANSI字符和Unicode字符)

    这篇文章主要介绍了C语言与C++中字符和字符串处理(ANSI字符和Unicode字符)的详细内容,非常的全面,这里推荐给大家,希望大家能够喜欢。
    2015-03-03
  • 详解C++实现线程安全的单例模式

    详解C++实现线程安全的单例模式

    这篇文章主要介绍了C++实现线程安全的单例模式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-03-03

最新评论