Qt Quick里的图形效果——混合(Blend)

来源:互联网 发布:买家如何联系淘宝客服 编辑:程序博客网 时间:2024/05/18 16:16

    Blend 元素用指定的模式混合两个 Item 。在我们使用 QPainter 绘图时,支持 Composition Modes ,Blend 干的事儿与此类似。

    使用 Blend 需要:

import QtGraphicalEffects 1.0


Blend元素简介

    Blend 是 Item 的派生类,有下列属性:

  • source,指定源Item
  • foregroundSource,指定作为前景的源 Item
  • mode,一个字符串,指定要使用的混合模式
  • cached,布尔变量,默认值为 false 。设置为 true ,可以缓存输出的效果图像,提升渲染效率,不过会占用更多的内存。如果源 Item 具有动态效果,建议禁用 cache 。

    Blend 元素本身是一个 Item ,你可以使用 anchors 来对它布局,也可以使用 x 、 y 、 width 、 height 等调整它的大小和位置。

    下面是 Qt 帮助里的示例代码:

import QtQuick 2.2import QtGraphicalEffects 1.0Item {    width: 300    height: 300    Image {        id: bug        source: "images/bug.jpg"        sourceSize: Qt.size(parent.width, parent.height)        smooth: true        visible: false    }    Image {        id: butterfly        source: "images/butterfly.png"        sourceSize: Qt.size(parent.width, parent.height)        smooth: true        visible: false    }    Blend {        anchors.fill: bug        source: bug        foregroundSource: butterfly        mode: "subtract"    }}

    如代码所示,Blend 对象指定了 source 、 foregroundSource 、 mode 三个属性。

    注意到 anchors.fill 属性了吗,它产生效果是: Blend 元素占据 bug 的位置,并且充满它。那实际上在定义 Blend 对象时也可以这样:

    Blend {        anchors.top: parent.top;        anchors.right: parent.right;        width: 240;        height: 240;        source: bug;        foregroundSource: butterfly;        mode: "subtract";    }

    值得一提的是,如果使用锚布局来定位 Blend 对象,那它锚定的 Item 必须是 Blend 的父或者兄弟。

    如你所见,示例代码将 bug 和 butterfly 的 visible 属性设置为 false ,这并不是必须的。如果我们将 Blend 元素当作是 source 、 foregroundSource 根据 mode 混合后的那个元素,理解起来就会容易得多。Blend 、 source 、 foregroundSource 是三个逻辑上相互独立的元素,你可以随意摆布它们,它们的位置、可见属性等相互没有任何影响。

Blend示例

    BlendExample.qml 演示了各种混合模式。效果图如下:


                    图 1 混合示例效果图

    如图 1 所示,界面分成两部分,上方是原始图片,下方是混合效果。

    我使用一个 ListView 展示 Blend 支持的所有混合模式,在 ListView 右侧显示混合结果,当选中 ListView 内的条目时,动态改变 Blend 的 mode 属性,Blend 就会重新混合两个源 Item ,我们就能看到新的混合效果。

    下面是 BlendExample.qml :

import QtQuick 2.2import QtGraphicalEffects 1.0import QtQuick.Controls 1.2Rectangle {    id: example;    signal back();    anchors.fill: parent;    Text {        id: origLabel;        x: 10;        y: 4;        font.pointSize: 20;        text: "Original Images";    }    Button {        anchors.right: parent.right;        anchors.top: parent.top;        anchors.margins: 4;        text: "Back";        onClicked: example.back();    }    Row {        id: origImages;        width: 500;        height: 260;        anchors.left: parent.left;        anchors.top: origLabel.bottom;        anchors.margins: 4;        spacing: 10;        Image {            source: "bug.jpg";            sourceSize: Qt.size(240, 240);            smooth: true;        }        Image {            source: "butterfly.png";            sourceSize: Qt.size(240, 240);            smooth: true;        }    }    Rectangle{        anchors.left: parent.left;        anchors.leftMargin: 4;        anchors.right: parent.right;        anchors.rightMargin: 4;        anchors.top: origImages.bottom;        height: 2;        border.width: 1;        border.color: "darkgray";    }    Text {        id: blendLabel;        anchors.top: origImages.bottom;        anchors.margins: 4;        anchors.left: parent.left;        font.pointSize: 20;        font.bold: true;        text: "Blend Modes && Effects";        color: "blue";    }    Rectangle {        id: blendModes;        anchors.left: parent.left;        anchors.leftMargin: 4;        anchors.top: blendLabel.bottom;        anchors.topMargin: 10;        anchors.bottom: parent.bottom;        anchors.bottomMargin: 4;        width: 160;        color: "gray";        ListView {            anchors.fill: parent;            clip: true;            focus: true;            delegate: Text {                id: wrapper;                text: name;                width: parent.width;                height: 36;                font.pointSize: 20;                Keys.onEnterPressed: {                    blender.mode = name;                    event.accepted = true;                }                Keys.onReturnPressed: {                    blender.mode = name;                    event.accepted = true;                }                MouseArea {                    anchors.fill: parent;                    onClicked: {                        wrapper.ListView.view.currentIndex = index;                        blender.mode = name;                    }                }            }            highlight: Rectangle {                width: parent.width;                color: "lightblue";            }            model: modesModel;        }    }    Image {        id: bug;        anchors.top: blendLabel.bottom;        anchors.topMargin: 10;        anchors.left: blendModes.right;        anchors.leftMargin: 10;        source: "bug.jpg";        sourceSize: Qt.size(300, 300);        smooth: true;        visible: false;    }    Image {        id: bufferFly;        source: "butterfly.png";        sourceSize: Qt.size(300, 300);        smooth: true;        visible: false;    }    Blend {        id: blender;        source: bug;        anchors.fill: bug;        foregroundSource: bufferFly;        mode: "subtract";    }    ListModel {        id: modesModel;        ListElement {            name: "subtract";        }        ListElement {            name: "normal";        }        ListElement {            name: "addition";        }        ListElement {            name: "average";        }        ListElement {            name: "colorBurn";        }        ListElement {            name: "color";        }        ListElement {            name: "colorDodge";        }        ListElement {            name: "darken";        }        ListElement {            name: "darkerColor";        }        ListElement {            name: "difference";        }        ListElement {            name: "divide";        }        ListElement {            name: "exclusion";        }        ListElement {            name: "hardLight";        }        ListElement {            name: "hue";        }        ListElement {            name: "lighten";        }        ListElement {            name: "lighterColor";        }        ListElement {            name: "lightness";        }        ListElement {            name: "multiply";        }        ListElement {            name: "negation";        }        ListElement {            name: "saturation";        }        ListElement {            name: "screen";        }        ListElement {            name: "softLight";        }    }}

    简单的分析一下代码。

返回

    图 1 右上角有一个 “Back” 按钮,点击后会发射一个 back() 信号。 back 信号用来通知我们在“Qt Quick里的图形效果(1)”中提到的 main.qml :用户要从当前示例返回了。 main.qml 收到 back 信号时,会销毁动态创建的示例组件。

    以后我们看到 ColorExample 等等针对某类效果设计的示例,都使用同一种策略。

混合

    混合模式列表使用 ListView 的展示,ListElement 只有一个角色——name,它的值就是混合模式的名字。当用户点击列表中的某个条目时, delegate 的 MouseArea 的 onClicked 信号处理器改变 Blend 元素的 mode 属性。


    好了,这次就到这里,每种混合模式效果如何,还请运行示例实际看一下。下次我们会介绍颜色(Color)效果。


--------

回顾一下我的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 图像处理实例之美图秀秀(附源码下载)
  • Qt Quick 之 PathView 详解
  • Qt Quick实例之挖头像
  • Qt Quick综合实例之文件查看器
  • Qt Quick调试之显示代码行号
  • Qt Quick实现的涂鸦程序
  • Qt Quick播放GIF动画
  • Qt Quick 中的 drag and drop(拖放)
  • Qt Quick里的AnimatedSprite的用法
  • Qt Quick里的粒子系统
  • Qt Quick实现的疯狂算数游戏
  • Qt Quick里的图形效果(Graphical Effects)
2 3