4. 颜色与填充:QColor的使用、渐变填充与纹理填充
颜色和填充,说白了就是给图形「上色」的功夫。我在做Qt项目时,发现很多新手画出来的东西总感觉「差点意思」,问题往往就出在颜色和填充上。今天咱们就把这块彻底聊透。
4.1 QColor:Qt的颜色管理核心
QColor是Qt里管理颜色的基础类。它支持RGB、HSV、CMYK等多种色彩模型。我个人习惯用RGB,因为直观——红绿蓝三个值,0到255,调起来方便。
核心用法:
QColor(r, g, b)— 用RGB值创建颜色QColor(r, g, b, a)— 带透明度(alpha通道)QColor("#FF8800")— 用十六进制字符串QColor("red")— 用预定义颜色名
// 创建颜色的几种方式
QColor c1(255, 0, 0); // 纯红色
QColor c2(0, 255, 0, 128); // 半透明绿色
QColor c3("#3366CC"); // 蓝色系
QColor c4(Qt::yellow); // 预定义黄色
// 获取颜色分量
int r = c1.red();
int g = c1.green();
int b = c1.blue();
int a = c1.alpha();
嗯,这里要注意:alpha值范围也是0-255,0是完全透明,255是不透明。我曾经在项目里把alpha设成了0.5,结果画了半天啥也看不见——Qt的alpha不接受浮点数。
4.2 渐变填充:让图形「活」起来
渐变填充是UI设计的利器。Qt提供了三种渐变:线性渐变、辐射渐变和锥形渐变。我最早接触渐变是在做仪表盘项目时,用辐射渐变模拟金属质感,效果出奇的好。
4.2.1 线性渐变(QLinearGradient)
线性渐变就是颜色沿着一条直线方向变化。你指定起点和终点,再设置几个颜色节点,Qt帮你自动插值。
QLinearGradient gradient(0, 0, 200, 0); // 从左到右
gradient.setColorAt(0.0, Qt::blue); // 起点:蓝色
gradient.setColorAt(0.5, Qt::green); // 中间:绿色
gradient.setColorAt(1.0, Qt::red); // 终点:红色
QBrush brush(gradient);
painter.setBrush(brush);
painter.drawRect(0, 0, 200, 100);
setColorAt的第一个参数是位置,范围0.0到1.0。你可以设置任意多个颜色节点。我个人习惯至少设3个点,这样过渡更自然。
小技巧:线性渐变的起点和终点坐标是相对于绘图坐标系的。如果你想渐变铺满整个矩形,就把起点设在矩形左边缘,终点设在右边缘。
4.2.2 辐射渐变(QRadialGradient)
辐射渐变是从一个中心点向外扩散。它需要指定中心点、半径,以及焦点位置。焦点是颜色最亮的地方,中心是渐变扩散的边界。
QRadialGradient gradient(100, 100, 100, // 中心(100,100),半径100
50, 50); // 焦点(50,50)
gradient.setColorAt(0.0, Qt::white);
gradient.setColorAt(0.5, Qt::yellow);
gradient.setColorAt(1.0, Qt::red);
QBrush brush(gradient);
painter.setBrush(brush);
painter.drawEllipse(0, 0, 200, 200);
为什么焦点和中心要分开?说白了就是为了模拟光照效果。焦点偏移一点,看起来就像光源从侧面打过来。我在做3D按钮效果时经常用这招。
4.2.3 锥形渐变(QConicalGradient)
锥形渐变是绕着中心点旋转的渐变。它只需要中心点和起始角度。颜色沿着圆周方向变化,像钟表一样。
QConicalGradient gradient(100, 100, 0); // 中心(100,100),起始角度0度
gradient.setColorAt(0.0, Qt::red);
gradient.setColorAt(0.25, Qt::yellow);
gradient.setColorAt(0.5, Qt::green);
gradient.setColorAt(0.75, Qt::blue);
gradient.setColorAt(1.0, Qt::red);
QBrush brush(gradient);
painter.setBrush(brush);
painter.drawEllipse(0, 0, 200, 200);
锥形渐变用得相对少一些,但在做仪表盘、雷达图、色轮选择器时特别好用。我记得有一次做音频可视化,用锥形渐变模拟频谱,效果非常炫酷。
4.3 纹理填充:用图片当「颜料」
纹理填充就是用一张图片来填充图形。Qt里用QPixmap或QImage配合QBrush实现。
QPixmap texture(":/images/brick.png"); // 从资源文件加载
QBrush brush(texture); // 用图片创建画刷
painter.setBrush(brush);
painter.drawRect(0, 0, 300, 200);
默认情况下,纹理是平铺的。如果你不想平铺,可以设置纹理的变换矩阵。不过说实话,我大部分时候就是直接平铺,省事。
避坑指南:我曾经在项目里用了一张很大的纹理图片,结果绘制性能惨不忍睹。后来改用小尺寸纹理(比如32x32或64x64),让Qt自动平铺,性能一下就上来了。纹理图片尽量小,这是经验之谈。
4.4 知识体系总览
下面这张图把颜色与填充的核心脉络梳理清楚了。你一看就明白各个部分的关系。
4.5 综合示例:把知识串起来
光说不练假把式。下面这个例子把颜色、渐变和纹理都用上了。你可以在自己的项目里试试。
void Widget::paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
// 1. 纯色填充
painter.setBrush(QColor("#FF6B6B"));
painter.drawRect(20, 20, 100, 100);
// 2. 线性渐变
QLinearGradient lg(140, 20, 240, 20);
lg.setColorAt(0.0, QColor("#4ECDC4"));
lg.setColorAt(1.0, QColor("#556270"));
painter.setBrush(lg);
painter.drawRect(140, 20, 100, 100);
// 3. 辐射渐变
QRadialGradient rg(320, 70, 50, 300, 70);
rg.setColorAt(0.0, Qt::white);
rg.setColorAt(0.5, QColor("#FFE66D"));
rg.setColorAt(1.0, QColor("#F7DC6F"));
painter.setBrush(rg);
painter.drawEllipse(270, 20, 100, 100);
// 4. 锥形渐变
QConicalGradient cg(420, 70, 0);
cg.setColorAt(0.0, QColor("#FF6B6B"));
cg.setColorAt(0.25, QColor("#4ECDC4"));
cg.setColorAt(0.5, QColor("#FFE66D"));
cg.setColorAt(0.75, QColor("#556270"));
cg.setColorAt(1.0, QColor("#FF6B6B"));
painter.setBrush(cg);
painter.drawEllipse(400, 20, 100, 100);
// 5. 纹理填充(用渐变模拟纹理)
QPixmap tex(20, 20);
tex.fill(Qt::transparent);
QPainter tp(&tex);
tp.fillRect(0, 0, 10, 10, QColor("#95A5A6"));
tp.fillRect(10, 10, 10, 10, QColor("#95A5A6"));
tp.end();
painter.setBrush(tex);
painter.drawRect(20, 140, 200, 100);
}
这个例子画了五个图形,每个用了不同的填充方式。你运行一下就能看到效果差异。我个人建议你动手改改参数,看看颜色变化,这样理解更深。
经验之谈:实际项目中,我经常把渐变和透明度结合使用。比如做一个半透明的遮罩层,用线性渐变从完全不透明过渡到完全透明,效果非常自然。你试试看。
好了,颜色与填充这块就聊到这儿。记住一句话:画刷(QBrush)是Qt绘图的「颜料盒」,颜色、渐变、纹理都是它的「颜料」。掌握了这些,你的Qt绘图就能从「能画」变成「画得好」。