【毕设笔记】Qt不规则图形的渐变填充

需求说明

最近写毕设时,需要利用Qt实现一个引向天线设计优化的软件,最近刚把计算模型搭建完毕,准备开始GUI界面设计。我的计划是先从天线的示意图开始做起,从一本天线英文书看到的示意图还不错,准备用Qt场景图元实现之,这样也方便用户添加与删除振子。
引向天线三维示意图

实现方法

关键类的认识

QPainterPath

简介

来自Qt手册
从描述中可以看到,一个QPainterPath可以看成是存放一些图形单元的容器,可以是线,椭圆最关键的是,他能用于填充,这是完成本需求的关键之一。

moveTo函数

来自Qt手册
这个函数形象地说,就是假设你手上拿着一支笔,你要从哪一点开始画起,但请注意他的说明:closing the previous one,也就是说,你如果前面添加的不是闭合曲线,该函数会将其闭合,比如你画了一个段弧,起始点为(x1,y1),终点为(x2,y2),你最后画完了调用moveTo(x1,y1)从终点回到起点,该函数会在(x1,y1)和(x2,y2)之间连一条直线使其闭合。

actTo函数

来自Qt手册
这是一个往QPainterPath添加圆弧的函数,参数分别为弧的外接矩形,开始角度,扫过的角度

lineTo

来自Qt手册
连线功能,连接当前点和指定的结束点。
注意:QPainterPath当前点是一直在变化的。假设你有一只笔,你画一条直线,你笔现在的所在位置就是QPainterPath的当前点

QLinearGradient

简介

来自Qt手册
渐变主要是通过该类实现的,可以从中看到,PadSpread方式和ReflectSpread方式都是可以实现该效果的。
通过该描述可以知道,我们可以通过SetColorAt函数添加一些点的颜色,该类会实现你指定的两点(两种颜色)之间的渐变效果。

setColorAt函数

SetColorAt函数说明
position参数相当于归一化处理,0为起始点,1为结束点,比如0.5为中间点,我们也可以添加很多个中间点(取值为0-1),插入很多个颜色。就拿我们要实现的需求来说,我们要实现从灰->白->灰这样的效果,我添加的三个点为(0,灰色)、(0.7,白色)、(1,灰色)

踩坑过程

盲目抄手册

看到手册那个arcTo函数的用法举例后,我以为要先调用moveTo把当前点移动到椭圆中心点,最后画出的图像是
踩坑图
中间多出来了一条线,搜了其他人的博客才发现这个问题

没有指定渐变类的起始点与终点

来自Qt手册我直接用错误图
没有参数的构造函数(因为前面手册也没有参数),导致我的柱子依然是白色的,没有渐变色。仔细看了一下手册才发现需要指定起始点和终点,这样子就是指定了渐变的方向,从起始点——>终点

乱用moveTo函数

没有看到moveTo的后半段说明,画一段调用一次moveTo,导致画出来的图像很不对
错误图片
注意往QPainterPath添加曲线时,一定要想象你如何一口气画完不规则曲线,而不要中间使用moveTo

最终结果与代码

无源振子

/*
 * 功能:绘制一根天线
 * 参数:天线的中心点,天线的长度,天线的半径
 *
 *
 * */
void Widget::drawAntPassive(QPointF center, qreal length,qreal radius)
{
    QPainter pr(this);
    pr.setRenderHint(QPainter::Antialiasing, true);//打开反走样
    QPen pen;
    pen.setWidthF(3);       //画笔相关

    pr.setPen(pen);
    QRectF rect(QPointF(center.x()-radius,center.y()-length-radius/2),
                QPointF(center.x()+radius,center.y()-length+radius/2)); //顶部椭圆外接矩形
    QRectF rect2(QPointF(center.x()-radius,center.y()+length-radius/2),
                 QPointF(center.x()+radius,center.y()+length+radius/2));//绘制棍子底部弧所需外接矩形
    pr.drawArc(rect,0,180*16);   //绘制棍子顶部椭圆的半圆,仿三维,因为顶部椭圆无色,接下去要用QPointerPath

    QPainterPath myPath;
    //这里画待填充渐变的区域,注意中间不要使用moveTo
    myPath.moveTo(center.x()-radius,center.y()-length);
    myPath.arcTo(rect,180.0f,180.0f);   //绘制上椭圆下半圆
    myPath.lineTo(QPointF(center.x()+radius,center.y()+length));    //右边竖线
    myPath.arcTo(rect2,0,-180.0f);
    myPath.lineTo(QPointF(center.x()-radius,center.y()-length));    //左边竖线

    QLinearGradient myGradient(QPointF(center.x()-radius,center.y()),QPointF(center.x()+radius,center.y()));
    //一定要指定开始点和结束点,标明绘制的方向,才能正常绘制渐变,这是我踩的一个坑
    //仿三维,渐变色
    //myGradient.setSpread(QGradient::ReflectSpread);

    myGradient.setColorAt(0,QColor(QString("#474747")));
    myGradient.setColorAt(0.7,QColor(QString("#FFFFFF")));
    myGradient.setColorAt(1,QColor(QString("#878787")));
    QBrush brh(myGradient);
    pr.setBrush(brh);
    pr.drawPath(myPath);
}

无源振子示意图

有源振子

有源振子只要在无源振子下加画一个源即可。代码如下

/**
 * @brief Widget::drawAntActive
 * @param center  天线的中点
 * @param length    天线的长度
 * @param radius    天线的半径
 */
void Widget::drawAntActive(QPointF center, qreal length, qreal radius)
{
    drawAntPassive(center,length,radius);

    //以下为绘制源
    QPainter pr(this);
    pr.setRenderHint(QPainter::Antialiasing, true);//打开反走样
    QPen pen;
    pen.setWidth(3);
    pr.setPen(pen);
    pr.setBrush(QBrush(Qt::white));
    QRectF rect(QPointF(center.x()-2*radius,center.y()-2*radius),
                QPointF(center.x()+2*radius,center.y()+2*radius));  //外部圆的外接矩形
    pr.drawEllipse(rect);   //源外部圆的绘制
    QRectF rect2(QPointF(center.x()-radius,center.y()-radius/2),
                QPointF(center.x(),center.y()+radius/2));  //外接矩形1
    pr.drawArc(rect2,0,180*16);
    QRectF rect3(QPointF(center.x(),center.y()-radius/2),
                QPointF(center.x()+radius,center.y()+radius/2));  //外接矩形2
    pr.drawArc(rect3,0,-180*16);
}

在这里插入图片描述
接下去只需要将这两个函数写进QGraphicsItem的paint虚函数即可

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值