Qt Quick里的图形效果——颜色(Color)

Qt Quick提供了通过改变一个 Item 的颜色来产生各种各样效果的元素。有下面几种:

  • BrightnessContrast,调整亮度和对比度
  • ColorOverlay,在源 Item 上覆盖一层颜色
  • Colorize,设置源 Item 的 HSL 颜色空间
  • Desaturate,降低颜色的饱和度
  • GammaAdjust,使用 gamma 曲线来改变源 Item 的照度
  • HueSaturation,在 HSL 颜色空间改变源 Item 的颜色
  • LevelAdjust,在 RGBA 颜色空间调整源 Item 的颜色水平

因为有多种颜色效果,每种又支持不同的、可调整的属性,所以在设计示例时和上次讲的 Blend 又有不同。

博客之星评选,点击投我一票,谢谢。投过了也可以点哦,每天都可以投投一票。

ColorExample示例介绍

我设计了一个示例: ColorExample.qml 。这个 QML 文档与 BlendExample 一样,都被加入到 GraphicalEffects 项目中的 qrc 中。使用到的图片 bug.jpg 和 butterfly.png 也在 qrc 中。

看一下效果:

图 1 颜色效果示例

如图 1 所示,界面分三个部分,与 Blend 示例类似。上方是原始图片,下方左侧是颜色效果类型列表,下方右侧用来展示某个效果类型的用法和效果。

如你所见,右下方白色背景那部分,会根据 Color Effects 列表中的条目而变化,是动态加载的,在代码中通过 Loader 来动态加载某个效果对应的 qml 文档。

到现在为止,我们的示例中的 qml 文档,已经分了三层:

  1. main.qml 构造最外层的示例框架
  2. ColorExample.qml 实现颜色效果的框架
  3. BrightnessContrastEx.qml 之类 qml 文档展示某个特定的颜色效果类的用法

颜色效果元素

颜色效果种类太多了,我真想说:看 Qt 帮助去吧。可这太不负责任了不是,所以我决定还是挑一个来讲一下,就挑 BrightnessContrast 吧,它不是最简单的,也不是复杂的。

与 Blend 类似的是,各种颜色效果元素操作 source 的结果是产生一个新的 Item 。不同的是,颜色效果元素只有一个 source 属性,没有 foregroundSource 属性,即:它只需要一个源 Item ,通过改变源 Item 的颜色来产生图形效果。

BrightnessContrast

看名字就知道了,这个元素是改变亮度和对比度的,所以它有两个属性, brightness 和 contrast ,分别改变源 Item (通过 source 属性指定)的亮度和对比度;它们的取值范围都是 -1.0 ~ 1.0 ,默认值都是 0.0 。

另外还有一个 cached 属性,介绍 Blend 时已经提到了,设置为 true 可以缓存处理后的图像,提高渲染速度。默认值为 false 。

每一个颜色效果的示例我都在一个单独的 qml 文档中实现,当用户点击图 1 中的颜色效果列表时,通过改变 Loader 的 source 属性来动态加载对应的 QML 文档。 BrightnessContrast 对应的 qml 文档是 BrightnessContrastEx.qml ,内容如下:

import QtQuick 2.2
import QtGraphicalEffects 1.0
import QtQuick.Controls 1.2

Rectangle {
    anchors.fill: parent;
    Image {
        id: opImage;
        x: 4;
        y: 4;
        width: 250;
        height: 250;
        source: "bug.jpg";
        sourceSize: Qt.size(250, 250);
        smooth: true;
        visible: false;
    }

    BrightnessContrast {
        anchors.fill: opImage;
        source: opImage;
        brightness: bslider.value;
        contrast: cslider.value;
    }
    Text {
        id: blabel;
        text: "Brightness:";
        anchors.left: opImage.left;
        anchors.top: opImage.bottom;
        anchors.margins: 4;
    }

    Slider {
        id: bslider;
        anchors.left: blabel.right;
        anchors.leftMargin: 8;
        anchors.verticalCenter: blabel.verticalCenter;
        width: 200;
        height: 40;
        minimumValue: -1.0;
        value: 0.5;
    }
    Text {
        id: clabel;
        text: "Contrast:";
        anchors.left: blabel.left;
        anchors.top: bslider.bottom;
        anchors.topMargin: 4;
    }

    Slider {
        id: cslider;
        anchors.left: bslider.left;
        anchors.verticalCenter: clabel.verticalCenter;
        width: 200;
        height: 40;
        minimumValue: -1.0;
        value: 0.5;
    }
}

看到 BrightnessContrast 对象的定义你可能觉得很熟悉,没错,和 “”一文中Blend 对象的定义类似。这里我把 brightness 属性绑定到 id 为 bslider 的滑块上,bslider 的 minimumValue 设置为 -1.0 ,默认的 maximumValue 默认为 1.0 ,不需要改变。 contrast 属性是类似的。

当我们拖动滑块时, BrightnessContrast 对象的相应属性值就会随着滑块的拖动而改变,我们看到的目标 Item 的效果就跟着变了。

LevelAdjust

这个是颜色效果里最复杂的了……说了这个就不说了,其它的就看帮助吧。先看下效果:

图2 LevelAdjust 效果

LevelAdjust 元素可以根据 gamma 曲线调整源 Item 的 R 、 G 、 B 三个通道的颜色值,这个比 GammaAdjust 更彪悍。 可以用 Qt.vector3d() 构造一个 3d 向量赋值给 LevelAdjust 的 gamma 属性,图 2 就是这么干的。如你所见,我把 3D 向量的构造代码显示出来了,你点击它,可以调出一个对话框,对话框上有三个 Slider 。如下图所示:

图 3 GammaVector对话框

这个对话框我定义在 GammaVector.qml 文档中,代码如下:

import QtQuick 2.2
import QtQuick.Dialogs 1.2
import QtQuick.Controls 1.2

Rectangle {
    id: gammaCreator;
    width: 250;
    height: 30;
    property vector3d gamma: Qt.vector3d(1.0, 1.0, 1.0);
    signal selected();
    color: "lightgray";
    border.width: 1;
    border.color: "darkgray";

    Text {
        id: gammaLabel;
        anchors.centerIn: parent;
        text: "Qt.vector3d(1.0, 1.0, 1.0)";
        color: "darkblue";
    }

    MouseArea {
        anchors.fill: parent;
        onClicked: vectorDlg.visible = true;
    }

    Dialog {
        id: vectorDlg;
        visible: false;
        width: 300;
        height: 200;
        standardButtons: StandardButton.Ok | StandardButton.Cancel;

        onAccepted: {
            gammaCreator.gamma = Qt.vector3d(one.value, two.value, three.value);
            gammaLabel.text = "Qt.vector3d(%1,%2,%3)".arg(one.value.toFixed(1)).arg(two.value.toFixed(1)).arg(three.value.toFixed(1));
            gammaCreator.selected();
        }

        Grid {
            x: 0;
            y: 4;
            width: 300;
            height: 120;
            verticalItemAlignment: Grid.AlignVCenter;
            columns: 3;
            Text {
                text: "0.0";
                width: 50;
                horizontalAlignment: Text.AlignRight;
            }
            Slider {
                id: one;
                minimumValue: 0.0;
                maximumValue: 10.0;
                value: 1.0;
                width: 180;
                height: 30;
            }
            Text {
                text: "10.0";
                width: 50;
            }

            Text {
                text: "0.0";
                width: 50;
                horizontalAlignment: Text.AlignRight;
            }
            Slider {
                id: two;
                minimumValue: 0.0;
                maximumValue: 10.0;
                value: 1.0;
                width: 180;
                height: 30;
            }
            Text {
                text: "10.0";
                width: 50;
            }

            Text {
                text: "0.0";
                width: 50;
                horizontalAlignment: Text.AlignRight;
            }
            Slider {
                id: three;
                minimumValue: 0.0;
                maximumValue: 10.0;
                value: 1.0;
                width: 180;
                height: 30;
            }
            Text {
                text: "10.0";
                width: 50;
            }
        }
    }
}

关于 QML 里 Dialog 元素的用法,请参考 Qt 帮助吧。

minimumInput 和 maximumInput 这两个属性是一对。 minimumInput 设定像素的黑色阈值,当一个像素的值小于 minimumInput 指定的颜色值时,就会被替换为黑色。maximumInput 设定像素的白色阈值,当一个像素的值大于 maximumInput 指定的颜色值时,就会被替换为白色。PhotoShop 里有这样的功能,可以批量把一个图片内低于给定值的像素修改为黑色。

minimumOutput 和 maximumOutput 是一对。minimumOutput 定义每个颜色通道的最小输出水平,这个值增加会让黑暗的区域变量,同时会降低对比度。maximumOutput 定义每个颜色通道的最大输出水平,减小这个值会让明亮的区域变暗,同时会降低对比度。

minimumInput 、 maximumInput 、 minimumOutput 、 maximumOutput 四个属性的取值范围都是 "#00000000" 到 "#FFFFFFFF"。

为了让用户能够选择一个颜色,我定义了一个单独的组件(ColorPicker.qml),如果你在图2中看到的那样,点击可以弹出一个颜色选择对话框,选择后这个组件就会改变自己的颜色,并将新颜色的值以字符串("#AARRGGBB")的形式显示出来。用起来还比较方便。

好了, LevelAdjust 介绍完了,我们看一下 LevelAdjustEx.qml 吧:

import QtQuick 2.2
import QtGraphicalEffects 1.0
import QtQuick.Controls 1.2

Rectangle {
    anchors.fill: parent;
    Image {
        id: opImage;
        x: 4;
        y: 4;
        width: 220;
        height: 220;
        source: "butterfly.png";
        sourceSize: Qt.size(220, 220);
        smooth: true;
        visible: false;
    }

    LevelAdjust {
        id: level;
        anchors.fill: opImage;
        source: opImage;
        minimumInput: minInput.color;
        maximumInput: maxInput.color;
        minimumOutput: minOutput.color;
        maximumOutput: maxOutput.color;
    }

    GammaVector {
        id: gammaSelector;
        anchors.left: opImage.left;
        anchors.top: opImage.bottom;
        anchors.topMargin: 4;
        onSelected: level.gamma = gammaSelector.gamma;
    }

    Grid {
        anchors.top: gammaSelector.bottom;
        anchors.topMargin: 4;
        anchors.left: gammaSelector.left;
        columns: 4;
        rowSpacing: 4;
        columnSpacing: 2;
        verticalItemAlignment: Grid.AlignVCenter;
        Text {
            text: "minimumInput:";
        }
        ColorPicker {
            id: minInput;
            width: 90;
            height: 28;
            color: "#00000000";
        }
        Text {
            text: "maximumInput:";
        }
        ColorPicker {
            id: maxInput;
            width: 90;
            height: 28;
            color: "#ffffffff";
        }
        Text {
            text: "minimumOutput:";
        }
        ColorPicker {
            id: minOutput;
            width: 90;
            height: 28;
            color: "#00000000";
        }
        Text {
            text: "maximumOutput:";
        }
        ColorPicker {
            id: maxOutput;
            width: 90;
            height: 28;
            color: "#ffffffff";
        }
    }
}

具体代码不分析了。

-------------------------

图 1 中列出的颜色效果元素,限于篇幅,就不一一介绍了,问道 Qt 帮助吧。

博客之星评选,点击投我一票,谢谢。投过了也可以点哦,每天都可以投投一票。

--------

回顾一下我的Qt Quick系列文章:

时间: 2024-10-20 03:13:07

Qt Quick里的图形效果——颜色(Color)的相关文章

Qt Quick里的图形效果:阴影(Drop Shadow)

Qt Quick提供了两种阴影效果: DropShow,阴影.这个元素会根据源图像,产生一个彩色的.模糊的新图像,把这个新图像放在源图像后面,给人一种源图像从背景上凸出来的效果. InnerShadow,内阴影.这个元素会根据源图像,产生一个彩色的.模糊的新图像,与 DropShadow不同的是,新图像会放在源图像里面. 效果 下面是我设计的示例效果. 首先是 DropShadow : 图1 阴影效果 然后是内阴影效果: 图2 内阴影效果 源码分析 如图1所示,界面被分为三部分. 最上面的是源图

Qt Quick里的图形效果——渐变(Gradient)

Qt Quick提供了三种渐变图形效果: ConicalGradient,锥形渐变 LinearGradient,线性渐变 RadialGradient,径向渐变 效果 下图是我设计的示例效果: 图 1 渐变图形效果 如图所示,第一行为线性渐变,第二行为锥形渐变,第三行为径向渐变. 渐变元素与其他图形效果元素不同之处在于:渐变元素既可以用来改变一个已有的元素(如Image),也有可以独立使用.如你在示例效果图中看到的那样,每一行前两个是独立使用渐变元素的效果,后两个是讲渐变效果应用到其它元素上的

Qt Quick里的粒子系统

就差您这一票了亲:博客之星评选,点击投我一票,谢谢.投过了也可以点哦,每天都可以投投一票. Qt Quick提供了一个粒子系统,提供了四种主要的 QML 类型: ParticleSystem ,粒子系统,它维护一个粒子系统相关的 Emitters . Painters . Affectors ,Emitters . Painters . Affectors 要想一起玩儿,就得指定同一个 ParticleSystem. ParticleSystem Painters , 它负责渲染一个粒子.Par

Qt Quick里的AnimatedSprite的用法

之前用 AnimatedImage 时一直对 AnimatedSprite 很奇怪,想试一下怎么用,一下子没试出来,放下了,后来一直没时间. OK ,今天想起来,又搞了一下. AnimatedSprite 说明 AnimatedSprite 元素用来播放精灵动画. 一些常见的属性解释: source 属性是 url 类型的,接受一个包含多帧的图片. frameWidth 和 frameHeight 指定帧大小. frameX 和 frameY 指定第一帧的左上角. frameCount 指定这个

Qt Quick核心编程从入门到精通

本文是个推荐文章,推荐foruok博主的Qt quick 核心编程的系列经典编程! foruok 博主 的Qt Quick系列文章: Qt Quick 简介 QML 语言基础 Qt Quick 之 Hello World 图文详解 Qt Quick 简单教程 Qt Quick 事件处理之信号与槽 Qt Quick事件处理之鼠标.键盘.定时器 Qt Quick 事件处理之捏拉缩放与旋转 Qt Quick 组件与对象动态创建详解 Qt Quick 布局介绍 Qt Quick 之 QML 与 C++

Qt Quick之StackView具体解释(1)

Qt Quick中有个StackView.我在<Qt Quick核心编程>一书中没有讲到.近期有人问起,趁机学习了一下,把它的基本使用方法记录下来. 我准备分两次来讲.第一次讲主要的使用方法.包含StackView的适用场景.基本属性和方法的使用方法.第二次讲一些略微复杂点的东西,比方被StackView管理的view的生命周期.delegate定制.查找等. 演示样例会用到动态创建组建,能够參考我之前的文章"Qt Quick 组件与对象动态创建具体解释".也会用到锚布局.

Qt Quick实现的涂鸦程序

之前一直以为 Qt Quick 里 Canvas 才可以自绘,后来发觉不是,原来还有好几种方式都可以绘图!可以使用原始的 OpenGL(Qt Quick 使用 OpenGL 渲染),可以构造QSGNode 来绘图,还可以使用 QPainter !哇, QPainter 我很熟悉啊.于是,我用 QPainter 结合 QML 实现了一个简单的涂鸦程序: PaintedItem .它有下列功能: 设置线条宽度 设置线条颜色 设置背景颜色 清除涂鸦 无限级undo 程序很简陋,效果如下: 图1 Pai

Qt Quick之StackView详解(1)

Qt Quick中有个StackView,我在<Qt Quick核心编程>一书中没有讲到,最近有人问起,趁机学习了一下,把它的基本用法记录下来. 我准备分两次来讲.第一次讲基本的用法,包括StackView的适用场景.基本属性和方法的用法.第二次讲一些稍微复杂点的东西,比如被StackView管理的view的生命周期.delegate定制.查找等. 示例会用到动态创建组建,可以参考我之前的文章"Qt Quick 组件与对象动态创建详解".也会用到锚布局,参考"Qt

Qt Quick 中的 drag and drop(拖放)

研究了一下 Qt Quick 里的 drag and drop 功能,大概讲一下. 类库 Qt Quick与 drag and drop 相关的,有这么几个类库: DropArea DragEvent Drag DropArea DropArea 其实是个方便类,它不可见,但是定义了一个可以接收拖放的区域.它的 entered 信号在有物体被拖入区域时发射,exited 信号在物体被拖出区域时发射,当物体在区域内被拖着来回移动时会不断发射 positionChanged 信号,当用户释放了物体,