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 知识体系总览

下面这张图把颜色与填充的核心脉络梳理清楚了。你一看就明白各个部分的关系。

颜色与填充知识体系 QBrush(画刷) QColor(颜色) RGB / HSV / CMYK Alpha透明度 渐变填充 QLinearGradient QRadialGradient QConicalGradient 纹理填充 QPixmap / QImage 平铺 / 缩放 / 变换 setBrush() → 应用到QPainter → 绘制图形

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绘图就能从「能画」变成「画得好」。

可可精品资料库