QTC零基础理论与实战QT渐变使用及

渐变有三种:QLinearGradient,QConicalGradientandQRadialGradient,接下来将介绍它们的使用和实现原理。

一、QLinearGradient

QLinearGradient是线性渐变,也就是颜色的各个分量(red,green,blue)在两点之间的变化是线性的,需要设置渐变的起始和结束坐标、颜色,超出渐变范围的填充方式,它并不能单独的使用,而是要和QBrush一起使用实现填充效果,主要有以下一些函数:

//创建QLinearGradient,同时设置起始和结束坐标

QLinearGradient(constQPointFstart,constQPointFfinalStop)

QLinearGradient(qrealx1,qrealy1,qrealx2,qrealy2)

//设置渐变的颜色,position的取值范围是[0.0,1.0]

setColorAt(qrealposition,constQColorcolor)

//超出渐变范围后的填充方式,默认使用PadSpread:

//QGradient::PadSpread

//QGradient::RepeatSpread

//QGradient::ReflectSpread

voidsetSpread(Spreadmethod)

//使用渐变创建画刷

QBrush(constQGradientgradient)

下图来自QLinearGradient的帮助文档,两个灰色的点表示渐变的起始和结束位置,从黄色渐变到有点发灰的黄色,同时展示了超出渐变范围时的三种填充方式:

为了介绍QLinearGradient的使用,下面的程序使用线性渐变,在垂直方向从红色渐变到蓝色,填充矩形QRect(20,20,,):

voidLinearGradientWidget::paintEvent(QPaintEvent*){

QPainterpainter(this);

painter.setRenderHint(QPainter::Antialiasing);

QRectrect(20,20,,);

//渐变开始的坐标为(20,20),结束的坐标为(20,)

QLinearGradientgradient(rect.x(),rect.y(),

rect.x(),rect.y()+rect.height());

gradient.setColorAt(0.0,Qt::red);

gradient.setColorAt(1.0,Qt::blue);

//超出渐变范围后的填充方式

gradient.setSpread(QGradient::ReflectSpread);

painter.setPen(Qt::NoPen);

painter.setBrush(gradient);//QBrush(constQGradientgradient)

painter.drawRect(rect);

}

如果不用QLinearGradient,怎么实现上面的渐变效果呢?也既是线性渐变的原理是什么呢?

以求线段上任意点的坐标为例,如图,已知线段的两端点A(x1,y1),B(x2,y2),求线段上任意一点M的坐标(x,y),则

根据两点的距离公式可以求出线段的长度

AB

(用

表示线段的长度)

t=

AM

/

AB

;

因为

AM

=0且

AM

=

AB

,所以t的值为[0.0,1.0],用length表示

AB

,则

x=x1+t*length

y=y1+t*length

t为0.0时M和A重合,t为1.0时M和B重合。

因为t的值为0到1之间,所以可以用循环求出AB上任意点的坐标

for(floatt=0.0;rate=1.0;t+=0.1){

x=x1+t*length;

y=y1+t*length;

}

其实这就是线段的参数方程。

上面可以理解为坐标的渐变,变化的是坐标的x,y分量,颜色的渐变理论上也是一样的,只不过要变化的是颜色的R,G,B三个分量。如果同时已知点A,B的坐标和颜色(r1,g1,b1),(r2,g2,b2),那么M点的坐标和颜色为:

for(floatt=0.0;rate=1.0;t+=0.1){

x=x1+t*length;

y=y1+t*length;

r=r1+t*(r2-r1);

g=g1+t*(g2-g1);

b=b1+t*(b2-b1);

}

也既是说,如果知道某个点对应的t,那么就能计算出此点的颜色。如下图,要在矩形内沿着AB进行渐变填充,已知点A,B的坐标和颜色,在矩形内任意一点N的坐标也是已知的(循环遍历矩形内所有的点),那么就可以求出点N在AB上的投影M(MN垂直于AB),t=

AM

/

AB

,使用上面的方法求出点M的颜色,点M的颜色就是点N的颜色。

对于下图垂直方向的渐变来说,点A(x1,y1)为矩形的左上角,点B(x2,y2)为矩形的坐下角,矩形内任意一点N(x,y)在AB上的投影M的坐标为(x1,y),所以t=(y-y1)/(y2-y1),知道了t,那么就能计算出对应的颜色了。

voidLinearGradientAlgorithmWidget::paintEvent(QPaintEvent*){

QPainterpainter(this);

painter.setRenderHint(QPainter::Antialiasing);

//渐变填充的矩形

QRectrect(20,20,,);

//渐变开始和结束的颜色

QColorgradientStartColor(,0,0);

QColorgradientFinalColor(0,0,);

intr1,g1,b1,r2,g2,b2;

gradientStartColor.getRgb(r1,g1,b1);

gradientFinalColor.getRgb(r2,g2,b2);

qrealy1=rect.y();

qrealy2=rect.y()+rect.height();

//计算矩形中每一个点的颜色,然后用此颜色绘制这个点

for(intx=rect.x();x=rect.x()+rect.width();++x){

for(inty=rect.y();y=rect.y()+rect.height();++y){

qrealt=(y-y1)/(y2-y1);

t=qMax(0.0,qMin(t,1.0));

intr=r1+t*(r2-r1);

intg=g1+t*(g2-g1);

intb=b1+t*(b2-b1);

painter.setPen(QColor(r,g,b));

painter.drawPoint(x,y);

}

}

}

运行程序,看看效果是不是和使用QLinearGradient的一样?

对于下图这样指定渐变的开始和结束位置,非垂直和水平方向渐变的实现,关键是求任意一点在另一条线上的投影,有很多方法和公式可以使用,这里我们使用QTransform进行移动,旋转求出t,计算出对应的颜色,由于QTransform的知识比较复杂,这里就不作深入介绍,有兴趣的可以自行查看相关文档。

voidLinearGradientAlgorithm2Widget::paintEvent(QPaintEvent*){

QPainterpainter(this);

painter.setRenderHint(QPainter::Antialiasing);

//渐变填充的矩形

QRectrect(20,20,,);

//渐变开始和结束的颜色、位置

QColorgradientStartColor(,0,0);

QColorgradientFinalColor(0,0,);

QPointgradientStartPoint(60,60);

QPointgradientFinalPoint(,);

//颜色分量

intr1,g1,b1,r2,g2,b2;

gradientStartColor.getRgb(r1,g1,b1);

gradientFinalColor.getRgb(r2,g2,b2);

qrealdx=gradientFinalPoint.x()-gradientStartPoint.x();

qrealdy=gradientFinalPoint.y()-gradientStartPoint.y();

qreallength=qSqrt(dx*dx+dy*dy);//渐变开始和结束的线段的长度

floatradian=qAtan2(dy,dx);//渐变方向和X轴的夹角

//先移动,后旋转,要先调用旋转的函数,然后在调用移动的函数,一定要注意这点,

//因为底层实现是matrix矩阵右乘点的坐标的列矩阵

QTransformtransform;

transform.rotateRadians(-radian);

transform.translate(-gradientStartPoint.x(),-gradientStartPoint.y());

//计算矩形中每一个点的颜色,然后用此颜色绘制这个点

for(intx=rect.x();x=rect.x()+rect.width();++x){

for(inty=rect.y();y=rect.y()+rect.height();++y){

QPointFp=transform.map(QPointF(x,y));

qrealt=p.x()/length;

t=qMax(0.0,qMin(t,1.0));

intr=r1+t*(r2-r1);

intg=g1+t*(g2-g1);

intb=b1+t*(b2-b1);

painter.setPen(QColor(r,g,b));

painter.drawPoint(x,y);

}

}

}

t0或t1时,即超出渐变范围后的填充方式是需要考虑的,我们这里的实现就是PadSpread的方式,怎么实现RepeatSpread和ReflectSpread的渐变呢?这个就作为大家的作业吧。

二、QRadialGradient

QRadialGradient名为径向渐变,在圆的范围内进行渐变,有三个主要参数:圆心、半径、焦点:

QRadialGradient(constQPointFcenter,qrealradius,

constQPointFfocalPoint)

QRadialGradient(constQPointFcenter,qrealradius)

圆心和半径确定颜色渐变的范围,焦点是渐变开始的点,渐变结束的点在圆周上。很多人都认为径向渐变是从圆心开始渐变的,其实不是这样的,只不过焦点和圆心默认是在同一个位置,所以看上去渐变好像是从圆心开始。

如图,我们故意设置圆心和焦点不在同一个位置,这样就能很明显的看到渐变的范围,开始和结束的位置,连接焦点和圆周的线上的点的颜色做线性渐变(是不是知道怎么实现QRadialGradient了?)。

voidRadialGradientWidget::paintEvent(QPaintEvent*){

QPainterpainter(this);

painter.setRenderHint(QPainter::Antialiasing);

painter.translate(width()/2,height()/2);

qrealradius=;//半径

QPointFcenter(0,0);//圆心

QPointFfocus(80,30);//焦点

//径向渐变

QRadialGradientgradient(center,radius,focus);

gradient.setColorAt(0.0,Qt::red);

gradient.setColorAt(1.0,Qt::blue);

//径向渐变填充圆

painter.setPen(Qt::darkGray);

painter.setBrush(gradient);

painter.drawEllipse(center,radius,radius);

//绘制圆心和焦点

painter.setBrush(Qt::gray);

painter.drawEllipse(center,4,4);

painter.drawEllipse(focus,4,4);

}

三、QConicalGradient

QConicalGradient名为角度渐变,在同一条半径上的像素的颜色值是相同的,只需要指定渐变的中心和开始的角度:

QConicalGradient(constQPointFcenter,qrealangle)

QConicalGradient(qrealcx,qrealcy,qrealangle)

经过线性渐变和径向渐变的学习,相信现在大家都能很容易的推断得出角度渐变的原理,这里就不作解释,作为悬念留给大家吧。

voidConicalGradientWidget::paintEvent(QPaintEvent*){

QPainterpainter(this);

painter.setRenderHint(QPainter::Antialiasing);

painter.translate(width()/2,height()/2);

qrealstartAngle=45;//渐变开始的角度

QPointFcenter(0,0);//渐变的中心

QConicalGradientgradient(center,startAngle);

gradient.setColorAt(0.0,Qt::red);

gradient.setColorAt(0.33,Qt::green);

gradient.setColorAt(0.66,Qt::blue);

gradient.setColorAt(1.0,Qt::red);

painter.setPen(Qt::darkGray);

painter.setBrush(gradient);

painter.drawEllipse(center,,);

}

声明:转载此文是出于传递更多信息之目的。若有来源标注错误或侵犯了您的合法权益,请作者持权属证明与本网联系,我们将及时更正、删除,谢谢。学到牛牛IT培训


转载请注明:http://www.aierlanlan.com/grrz/2894.html

  • 上一篇文章:
  •   
  • 下一篇文章: 没有了