Qt 学习之路 2(27):渐变
Qt 学习之路 2(27):渐变
渐变是绘图中很常见的一种功能,简单来说就是可以把几种颜色混合在一起,让它们能够自然地过渡,而不是一下子变成另一种颜色。渐变的算法比较复杂,写得不好的话效率会很低,好在很多绘图系统都内置了渐变的功能,Qt 也不例外。渐变一般是用在填充里面的,所以,设置渐变是在QBrush里面。
Qt 提供了三种渐变:线性渐变(QLinearGradient)、辐射渐变(QRadialGradient)和角度渐变(QConicalGradient)。我们可以在 Qt API 手册中看到这几种渐变的区别:
线性渐变:
辐射渐变:
角度渐变:
具体细节可以参考文档。下面我们通过一个示例看看如何使用渐变进行填充:
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing, true);
    QLinearGradient linearGradient(60, 50, 200, 200);
    linearGradient.setColorAt(0.2, Qt::white);
    linearGradient.setColorAt(0.6, Qt::green);
    linearGradient.setColorAt(1.0, Qt::black);
    painter.setBrush(QBrush(linearGradient));
    painter.drawEllipse(50, 50, 200, 150);
}
| 
 1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
 | 
 void paintEvent(QPaintEvent *) 
{ 
    QPainter painter(this); 
    painter.setRenderHint(QPainter::Antialiasing, true); 
    QLinearGradient linearGradient(60, 50, 200, 200); 
    linearGradient.setColorAt(0.2, Qt::white); 
    linearGradient.setColorAt(0.6, Qt::green); 
    linearGradient.setColorAt(1.0, Qt::black); 
    painter.setBrush(QBrush(linearGradient)); 
    painter.drawEllipse(50, 50, 200, 150); 
} 
 | 
像以前一样,我们也只给出了paintEvent()的代码。这段代码看起来也相当清晰:首先我们打开了反走样,然后创建一个QLinearGradient对象实例。QLinearGradient也就是线性渐变,其构造函数有四个参数,分别是 x1,y1,x2,y2,即渐变的起始点和终止点。在这里,我们从 (60, 50) 点开始渐变,到 (200, 200) 点止。关于坐标的具体细节,我们会在后面的章节中详细介绍。渐变的颜色是在setColorAt()函数中指定的。下面是这个函数的签名:
| 
 1 
 | 
 void QGradient::setColorAt ( qreal position, const QColor & color ) 
 | 
这个函数的作用是,把 position 位置的颜色设置成 color。其中,position 是一个 [0, 1] 闭区间的数字。也就是说,position 是相对于我们建立渐变对象时做的那个起始点和终止点区间的一个比例。以这个线性渐变为例,在从 (60, 50) 到 (200, 200) 的线段上,在 0.2,也就五分之一处设置成白色,在 0.6 也就是五分之三处设置成绿色,在 1.0 也就是终点处设置成黑色。创建QBrush对象时,把这个渐变对象传递进去,然后就可以运行了:

下面我们开始一个更复杂,也更实用一些的例子:绘制一个色轮(color wheel)。所谓色轮,其实就是一个带有颜色的圆盘(或许你没听说过这个名字,但是你肯定见过这个东西),下面是色轮的运行结果:

我们来看看它的代码:
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
const int r = 150;
    QConicalGradient conicalGradient(0, 0, 0);
conicalGradient.setColorAt(0.0, Qt::red);
    conicalGradient.setColorAt(60.0/360.0, Qt::yellow);
    conicalGradient.setColorAt(120.0/360.0, Qt::green);
    conicalGradient.setColorAt(180.0/360.0, Qt::cyan);
    conicalGradient.setColorAt(240.0/360.0, Qt::blue);
    conicalGradient.setColorAt(300.0/360.0, Qt::magenta);
    conicalGradient.setColorAt(1.0, Qt::red);
painter.translate(r, r);
QBrush brush(conicalGradient);
    painter.setPen(Qt::NoPen);
    painter.setBrush(brush);
    painter.drawEllipse(QPoint(0, 0), r, r);
}
| 
 1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
 | 
 void ColorWheel::paintEvent(QPaintEvent *) 
{ 
    QPainter painter(this); 
    painter.setRenderHint(QPainter::Antialiasing); 
    const int r = 150; 
    QConicalGradient conicalGradient(0, 0, 0); 
    conicalGradient.setColorAt(0.0, Qt::red); 
    conicalGradient.setColorAt(60.0/360.0, Qt::yellow); 
    conicalGradient.setColorAt(120.0/360.0, Qt::green); 
    conicalGradient.setColorAt(180.0/360.0, Qt::cyan); 
    conicalGradient.setColorAt(240.0/360.0, Qt::blue); 
    conicalGradient.setColorAt(300.0/360.0, Qt::magenta); 
    conicalGradient.setColorAt(1.0, Qt::red); 
    painter.translate(r, r); 
    QBrush brush(conicalGradient); 
    painter.setPen(Qt::NoPen); 
    painter.setBrush(brush); 
    painter.drawEllipse(QPoint(0, 0), r, r); 
} 
 | 
首先还是新建 QPainter 对象,开启反走样。然后我们将圆盘半径定义为 150。下面创建一个角度渐变实例,其构造函数同样接受三个参数:
| 
 1 
 | 
 QConicalGradient::QConicalGradient ( qreal cx, qreal cy, qreal angle ) 
 | 
前两个参数 cx 和 cy 组成角度渐变的中心点,第三个参数是渐变的起始角度。在我们的例子中,我们将渐变中心点设置为 (0, 0),起始角度为 0。类似线性渐变,角度渐变的setColorAt()函数同样接受两个参数,第一个是角度比例,第二个是颜色。例如,
| 
 1 
 | 
 conicalGradient.setColorAt(0.0, Qt::red); 
 | 
将 0 度角设置为红色;
| 
 1 
 | 
 conicalGradient.setColorAt(60.0/360.0, Qt::yellow); 
 | 
将 60 度角设置为黄色。由于一个圆周是 360 度,所以 60.0/360.0 即是这个角度的比例。其余代码以此类推。最后一句,我们将 1.0 处设置为红色,也就是重新回到起始处。至于颜色的分布,这是由颜色空间定义的,有兴趣的朋友可以查阅有关颜色模型的理论。
| 
 1 
 | 
 painter.translate(r, r); 
 | 
这是我们唯一不熟悉的函数。QPainter::translate(x, y)函数意思是,将坐标系的原点设置到 (x, y) 点。原本坐标系原点位于左上角,我们使用translate(r, r),将坐标原点设置为 (r, r)。这么一来,左上角的点的坐标就应该是 (-r, -r)。
最后,我们使用drawEllipse()函数绘制圆盘。注意,由于我们已经把坐标原点设置为 (r, r),因此,在绘制时,圆心应该是新的坐标 (0, 0),而不是原来的 (r, r)。
PS:为了理解translate()函数的作用,可以思考下,如果去掉translate()函数的调用,我们的程序应该如何修改。答案是:
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
const int r = 150;
    QConicalGradient conicalGradient(r, r, 0);
conicalGradient.setColorAt(0.0, Qt::red);
    conicalGradient.setColorAt(60.0/360.0, Qt::yellow);
    conicalGradient.setColorAt(120.0/360.0, Qt::green);
    conicalGradient.setColorAt(180.0/360.0, Qt::cyan);
    conicalGradient.setColorAt(240.0/360.0, Qt::blue);
    conicalGradient.setColorAt(300.0/360.0, Qt::magenta);
    conicalGradient.setColorAt(1.0, Qt::red);
QBrush brush(conicalGradient);
    painter.setPen(Qt::NoPen);
    painter.setBrush(brush);
    painter.drawEllipse(QPoint(r, r), r, r);
}
| 
 1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
 | 
 void ColorWheel::paintEvent(QPaintEvent *) 
{ 
    QPainter painter(this); 
    painter.setRenderHint(QPainter::Antialiasing); 
    const int r = 150; 
    QConicalGradient conicalGradient(r, r, 0); 
    conicalGradient.setColorAt(0.0, Qt::red); 
    conicalGradient.setColorAt(60.0/360.0, Qt::yellow); 
    conicalGradient.setColorAt(120.0/360.0, Qt::green); 
    conicalGradient.setColorAt(180.0/360.0, Qt::cyan); 
    conicalGradient.setColorAt(240.0/360.0, Qt::blue); 
    conicalGradient.setColorAt(300.0/360.0, Qt::magenta); 
    conicalGradient.setColorAt(1.0, Qt::red); 
    QBrush brush(conicalGradient); 
    painter.setPen(Qt::NoPen); 
    painter.setBrush(brush); 
    painter.drawEllipse(QPoint(r, r), r, r); 
} 
 | 
不仅我们需要修改最后的绘制语句,还需要注意修改QConicalGradient定义时传入的中心点的坐标。
Qt 学习之路 2(27):渐变的更多相关文章
- Qt 学习之路 2(66):访问网络(2)
		
Home / Qt 学习之路 2 / Qt 学习之路 2(66):访问网络(2) Qt 学习之路 2(66):访问网络(2) 豆子 2013年10月31日 Qt 学习之路 2 27条评论 上一 ...
 - Qt 学习之路 2(30):Graphics View Framework
		
Qt 学习之路 2(30):Graphics View Framework 豆子 2012年12月11日 Qt 学习之路 2 27条评论 Graphics View 提供了一种接口,用于管理大量自定义 ...
 - Qt 学习之路 2(25):画刷和画笔
		
Home / Qt 学习之路 2 / Qt 学习之路 2(25):画刷和画笔 Qt 学习之路 2(25):画刷和画笔 豆子 2012年11月5日 Qt 学习之路 2 17条评论 前面一章我们提 ...
 - Qt 学习之路 2(71):线程简介
		
Qt 学习之路 2(71):线程简介 豆子 2013年11月18日 Qt 学习之路 2 30条评论 前面我们讨论了有关进程以及进程间通讯的相关问题,现在我们开始讨论线程.事实上,现代的程序中,使用线程 ...
 - Qt 学习之路 2(67):访问网络(3)
		
Qt 学习之路 2(67):访问网络(3) 豆子 2013年11月5日 Qt 学习之路 2 16条评论 上一章我们了解了如何使用我们设计的NetWorker类实现我们所需要的网络操作.本章我们将继续完 ...
 - Qt 学习之路 2(65):访问网络(1)
		
Home / Qt 学习之路 2 / Qt 学习之路 2(65):访问网络(1) Qt 学习之路 2(65):访问网络(1) 豆子 2013年10月11日 Qt 学习之路 2 18条评论 现在 ...
 - Qt 学习之路 2(64):使用 QJsonDocument 处理 JSON
		
Home / Qt 学习之路 2 / Qt 学习之路 2(64):使用 QJsonDocument 处理 JSON Qt 学习之路 2(64):使用 QJsonDocument 处理 JSON 豆子 ...
 - Qt 学习之路 2(63):使用 QJson 处理 JSON
		
Home / Qt 学习之路 2 / Qt 学习之路 2(63):使用 QJson 处理 JSON Qt 学习之路 2(63):使用 QJson 处理 JSON 豆子 2013年9月9日 Qt ...
 - Qt 学习之路 2(62):保存 XML
		
Home / Qt 学习之路 2 / Qt 学习之路 2(62):保存 XML Qt 学习之路 2(62):保存 XML 豆子 2013年8月26日 Qt 学习之路 2 9条评论 前面几章我们 ...
 
随机推荐
- GO语言文件的创建与打开实例分析
			
本文实例分析了GO语言文件的创建与打开用法.分享给大家供大家参考.具体分析如下: 文件操作是个很重要的话题,使用也非常频繁,熟悉如何操作文件是必不可少的.Golang 对文件的支持是在 os pack ...
 - Oracle 环境下 GoldenGate 集成抽取(Integrated Capture)模式与传统抽取模式(Classic Capture)间的切换
			
检查抽取进程模式 在 GGSCI 环境下,执行类似如下语句查看特定进程的状态. GGSCI> info <Group_Name> 其中,<Group_Name> 为进程名 ...
 - 1-2 开发环境搭建-Windows平台
			
C:\Program Files\nodejs\node_modules\npm\npmrc C:\Users\ZHONGZHENHUA\.android\avd H:\heimaandroidadt ...
 - libevent源码深度剖析一
			
libevent源码深度剖析一 ——序幕 张亮 1 前言 Libevent是一个轻量级的开源高性能网络库,使用者众多,研究者更甚,相关文章也不少.写这一系列文章的用意在于,一则分享心得:二则对libe ...
 - SpringAOP03 项目脚手架、自定义注解、织入切面、引介增强
			
1 项目脚手架 利用 Maven 进行创建 1.1 利用IDEA创建一个Maven原型项目 技巧01:原型Maven项目是没有webapp文件夹和resources项目文件夹的,需要自己手动创建:创建 ...
 - Hadoop完全分布式环境搭建(三)——基于Ubuntu16.04安装和配置Java环境
			
[系统环境] 1.宿主机OS:Win10 64位 2.虚拟机软件:VMware WorkStation 12 3.虚拟机OS:Ubuntu16.04 4.三台虚拟机 5.JDK文件:jdk-8u201 ...
 - Django--static静态文件引用
			
需求 引用静态文件的目录不写死 "django.core.context_processors.static", html引用 1 <script src="{{ ...
 - nodelet的应用
			
1.创建一个包,如example_pkg catkin_create_pkg example_pkg 2.创建MyNodeletClass.h文件 cd ~/catkin_ws/src/example ...
 - C# Code 非常好的学习博客
			
https://ardalis.com/how-to-become-master-writing-c-code
 - 关于pycharm字体大小的调整
			
我们平常编写pyhton 可以用sublime eclipse 但是eclipse在后期需要安装很多插件,这很是麻烦,为了避免这种麻烦,我们采用pycharm来编写,但是刚装上的该软件 不建议同学们进 ...