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

2015-01-24 13:18:31 · 作者: · 浏览: 10

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

使用 Blend 需要:

import QtGraphicalEffects 1.0

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

Blend元素简介

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

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

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

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

import QtQuick 2.2
import QtGraphicalEffects 1.0

Item {
    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.2
import QtGraphicalEffects 1.0
import QtQuick.Controls 1.2

Rectangle {
    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;
                }

                MouseAre