Qt本身是没有路径渐变的,只提供了三种基本的渐变类型:

常见的解决方案是,对路径分段进行线性渐变填充,本文也是采用该方法,效果如下:

主要用到 QPainterPath 的两个接口:length 路径整体长度,和 pointAtPercent 根据百分比求路径上点坐标。pointAtPercent 是一个较为费时的函数,尽量不放在 paintEvent 中计算,避免卡顿。

qreal QPainterPath::length() const
QPointF QPainterPath::pointAtPercent(qreal t) const

先根据分片端点长度偏移量除以总长得到百分比值,就能求得分片端点坐标。 (为什么不直接对总长分固定段数,比如分成 100 份呢?这样在路径长度不一致时渐变的疏密程度也会不一致)

    double len = path.length();int step = 6;for(int i=0;i<len;i+=step){QPointF pt1=path.pointAtPercent(i/len);QPointF pt2=path.pointAtPercent((i+step)<len?((i+step)/len):1.0);//... ...}

还要注意,一个路径中可以包含多个子路径,两个子路径可能没有相连,根据百分比取值时需要判断两个点之间的距离是否大于了分片的长度。

    double len = path.length();int step = 6;QPointF pt1=path.pointAtPercent(0);QPointF pt2=pt1;for(int i=0;i<len;i+=step){pt1=pt2;int i2 = i+step;pt2=path.pointAtPercent(i2<len?(i2/len):1.0);//两点距离过长说明是到了另一段子路径上//那就往前找当前子路径的末尾while(QVector2D(pt1).distanceToPoint(QVector2D(pt2))>step+1){i2--;pt2=path.pointAtPercent(i2<len?(i2/len):1.0);}//... ...//下一个子路径的端点if(i2!=i+step){i2++;pt2=path.pointAtPercent(i2<len?(i2/len):1.0);}}

分片路径有了,就是填充渐变的颜色表计算了。我这里为了省事直接 QLinearGradient 填充到 QImage 上,再根据步进换算成坐标取对应的值。

分段填充来实现路径渐变存在一些问题,比如计算量大容易卡顿;多次叠加导致抗锯齿效果不好。

代码链接: https://github.com/gongjianbo/MyTestCode/tree/master/Qt/PathGradient

主要代码:

#pragma once
#include <QMainWindow>class MainWindow : public QMainWindow
{Q_OBJECT
public:MainWindow(QWidget *parent = nullptr);~MainWindow();protected:void paintEvent(QPaintEvent *event) override;private://动画偏移量int offset = 0;
};
#include "mainwindow.h"#include <QPaintEvent>
#include <QPainter>
#include <QPainterPath>
#include <QLinearGradient>
#include <QVector2D>
#include <QTimer>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)
{setWindowTitle("Path && Gradient");resize(400, 300);//定时器更新颜色偏移QTimer *timer =new QTimer(this);connect(timer,&QTimer::timeout,this,[this]{offset++;offset %= 100;update();});timer->start(50);
}MainWindow::~MainWindow()
{
}void MainWindow::paintEvent(QPaintEvent *event)
{event->accept();QPainter p(this);p.fillRect(rect(),Qt::black);//将圆弧和贝塞尔曲线添加到路径中QRect rt=QRect(100,50,200,200);QPainterPath path;path.moveTo(300,150);path.arcTo(rt,0,-250);path.moveTo(50,150);path.cubicTo(150,50,250,250,350,150);//颜色表,先绘制到img,再根据坐标取颜色值QLinearGradient gradient(QPointF(0,0),QPointF(0,100));gradient.setColorAt(0,Qt::red);gradient.setColorAt(0.333,Qt::green);gradient.setColorAt(0.666,Qt::blue);gradient.setColorAt(1,Qt::red);QImage img(1,100,QImage::Format_ARGB32);QPainter imgp(&img);imgp.fillRect(img.rect(),gradient);QPen pen;pen.setColor(Qt::white);pen.setWidth(16);p.setPen(pen);p.setRenderHint(QPainter::Antialiasing);//根据路径长度和分片长度来取路径百分比坐标和颜色//注意:pointAtPercent比较耗时,可以在resizeEvent等地方计算好坐标点double len = path.length();int step = 6;QPointF pt1=path.pointAtPercent(0);QPointF pt2=pt1;for(int i=0;i<len;i+=step){//根据分片长度获取两端的坐标pt1=pt2;int i2 = i+step;pt2=path.pointAtPercent(i2<len?(i2/len):1.0);//两点距离过长说明是到了另一段子路径上//那就往前找当前子路径的末尾while(QVector2D(pt1).distanceToPoint(QVector2D(pt2))>step+1){i2--;pt2=path.pointAtPercent(i2<len?(i2/len):1.0);}//从颜色表取对应的颜色值QColor color1=img.pixelColor(0,(i/step+offset)%100);QColor color2=img.pixelColor(0,((i+step)/step+offset)%100);QLinearGradient lg(pt1,pt2);lg.setColorAt(0,color1);lg.setColorAt(1,color2);//根据两端颜色设置渐变,然后填充该分片pen.setBrush(lg);p.setPen(pen);p.drawLine(pt1,pt2);//下一个子路径的端点if(i2!=i+step){i2++;pt2=path.pointAtPercent(i2<len?(i2/len):1.0);}}
}

Qt实现路径渐变,绘制彩色的线条相关推荐

  1. VC++ 利用MFC的CWindowDC类实现画线功能 在桌面窗口中画线 绘制彩色线条 CPen nPenStyle nWidth crColor

    目录 利用MFC的CWindowDC类实现画线功能 在桌面窗口中画线 绘制彩色线条 CPen nPenStyle nWidth crColor 接上:VC++ 绘制线条 OnLButtonDown函数 ...

  2. Qt总结之八:绘制仪表盘

    前言 (1)QPainter用来执行具体的绘图相关的操作,用来画点,线,填充,变换,alpha/阿尔法通道(透明度)  *Appha的值越大,就越不透明,范围是0-255,255就是不透明,0就是完全 ...

  3. 【OpenGL】十二、OpenGL 绘制线段 ( 绘制单条线段 | 绘制多条线段 | 依次连接的点组成的线 | 绘制圈 | 绘制彩色的线 )

    文章目录 一.设置线宽度 二.绘制单条线段 GL_LINES 三.绘制多条线段 GL_LINES 四.绘制依次连接的点组成的线 GL_LINE_STRIP 五.绘制圈 GL_LINE_LOOP ( 偶 ...

  4. Linux 平台下基于Qt 的电子地图的绘制

    Linux 平台下基于Qt 的电子地图的绘制 摘要-------------------------------------------1   关键词------------------------- ...

  5. Qt OpenGL(二十八)——Qt OpenGL 核心模式-绘制一个正方体(正六面体)

    Qt OpenGL(二十七)--Qt OpenGL 核心模式-绘制一个正方体(正六面体) 截止到上一篇文章,一川想使用Qt封装的类绘制一个旋转的彩色三角形的目标就实现了. 上一篇在介绍了使用变换矩阵的 ...

  6. canvas在path路径上绘制文字

    1.代码及解释如下: public class Main3Activity extends Activity {@Overrideprotected void onCreate(Bundle save ...

  7. linux 终端 渐变色,QT学习笔记-渐变填充

    渐变,是指逐渐的,有规律性的变化,是一种规律性很强的现象.提供了一个与渐变相关的QGradient类,目前支持三种渐变画刷,分别是线性渐变(QLinearGradient).辐射渐变(QRadialG ...

  8. R语言CRAN不包含的安装包下载并手动使用RStudio进行安装实战:以下载VRPM包及绘制彩色列线图为例

    R语言CRAN不包含的安装包下载并手动使用RStudio进行安装实战:以下载VRPM包及绘制彩色列线图为例 目录

  9. GDI+ 学习记录(11): 路径渐变画刷 - PathGradientBrush

    为什么80%的码农都做不了架构师?>>>    //路径渐变画刷 varg: TGPGraphics;path: TGPGraphicsPath;pb: TGPPathGradien ...

最新文章

  1. php session 二位数组
  2. HTTP 错误 500.19- Internal Server Error 错误解决方法
  3. 部分设备在微信内无法播放audio的解决方案
  4. 关于小程序云开发的一些经典问题处理
  5. 【字符集UTF8】处理Toad显示乱码及Windows XP下无法插入“某些汉字”问题
  6. NAT类型及检测方法
  7. HLG 1357 Leyni,罗莉和怪叔叔
  8. pulsar常用命令
  9. C++ 解引用操作符重载
  10. spring源码 第二个后置处理器方法的使用-推断构造函数
  11. 文件夹加密软件排行榜
  12. c语言圆周率天书解释,c语言天书圆周率的计算及分析.doc
  13. PHP轻量级博客 typecho插件安装教程
  14. 网站如何设置一个小图标
  15. java验证码提交错误时_验证码输入错误后自动刷新验证码
  16. 内存卡删除的文件如何恢复?如何恢复比较快?
  17. 画板数据保存成文件的两种方法小结
  18. 华为数通笔记-组播协议介绍之PIM
  19. ssm+mysql+基于微信平台的牙科就诊信息管理系统的设计与实现 毕业设计-附源码211157
  20. Web服务技术与应用

热门文章

  1. 计算机专业毕业英文论文一万字,计算机专业毕业论文外文翻译2篇共15页.DOC
  2. magento会员邮件找回密码连接无效
  3. lodop 打印说明
  4. 文正·高等数学每日一题(1)·极限
  5. SpringBoot常用注解
  6. 淘宝开发平台店铺商品上传接口,店铺订单交易接口,店铺订单解密接口,店铺上下架接口,店铺订单推送接口(整理好的完整店铺上货订单操作接口)
  7. 使用deconvblind估计PSF
  8. 词霸天下---词根252【-emper- = -imper- 命 令】
  9. 一些设计模式阐述,偏JAVA实现
  10. web3.js链接以太坊并查询钱包u余额