Qt Quick里的图形效果(Graphical Effects)

版权声明:本文为foruok原创文章,转载请通过订阅号“程序视界”联系foruok获取授权。 https://blog.csdn.net/foruok/article/details/42619649

    Qt Quick 提供了 Graphical Effects ,我在《Qt Quick核心编程》一书中限于篇幅没有介绍,这里补上吧。

    Graphical Effects ,姑且叫作图形效果吧。它提供了 Blend 、 Color 等好几类效果,有些类别下面又有多种不同的效果,要介绍完整需要较长的篇幅。我们一个一个来看。

概要介绍

    先看看都有哪几类图形效果(Graphical Effects)吧:

  • Blend,混合。只有一种类型——Blend,使用一种混合模式来合并两个源 items 。
  • Color,颜色,通过改变一个 Item 的颜色来产生各种各样的效果。有下列几种类型:
    • BrightnessContrast,调整亮度和对比度
    • ColorOverlay,在源 Item 上覆盖一层颜色
    • Colorize,设置源 Item 的 HSL 颜色空间
    • Desaturate,降低颜色的饱和度
    • GammaAdjust,使用 gamma 曲线来改变源 Item 的照度
    • HueSaturation,在 HSL 颜色空间改变源 Item 的颜色
    • LevelAdjust,在 RGBA 颜色空间调整源 Item 的颜色水平
  • Gradient,渐变。有下列几种类型:
    • ConicalGradient,锥形渐变
    • LinearGradient,线性渐变
    • RadialGradient,径向渐变
  • Distortion,变形。只有一种类型——Displace,根据给定的位移 map 来改变源 Item 的像素
  • Drop Shadow,投影。有两种类型:
    • DropShadow,根据源 Item 产生一个彩色的、模糊的影子图像,并且把它放到原始图像的后面,会产生源 Item 在背景上凸起的效果
    • InnerShadow,在源 Item 里面产生一个彩色的、模糊的图像
  • Blur,模糊。有下面几种类型:
    • FastBlur,快速模糊
    • GaussianBlur,高斯模糊
    • MaskedBlur,差异化模糊,可以根据一个掩码元素对源 Item 的不同区域产生强度不同的模糊效果
    • RecursiveBlur,递归模糊。通过反复模糊来产生很强的模糊效果。
  • Motion Blur,运动模糊。有下面几种类型:
    • DirectionalBlur,定向模糊,在指定的方向上产生模糊效果
    • RadialBlur,径向模糊,在以源 Item 的中心点为圆心的一个圆形内应用定向模糊
    • ZoomBlur,缩放模糊,朝着源 Item 的中心点应用定向模糊
  • Glow,发光。有下面几种类型:
    • Glow,根据源 Item 产生一个彩色的、模糊的发光效果图像,并且把它放到源 Item 后面,产生一种源 Item 在发光的效果。
    • RectangularGlow,生成一个模糊的、彩色的矩形,给人发光的印象
  • Mask,遮罩。有下面几种类型:
    • OpacityMask,透明遮罩。用另一个 Item 遮挡源 Item
    • ThresholdMask,阈值遮罩。用另一个 Item 遮挡源 Item,根据一个阈值来应用遮挡效果

示例项目

    我设计了一个示例来演示所有的图形效果,它是一个 Qt Quick App 项目。下面是示例运行后的首页:


                        图 1 示例首页

    我们结合图 1 来介绍一下示例项目的结构。

    如图 1 所示,首页中间是一个列表,列出了所有的图形效果类别。

    界面底部右侧有两个按钮,“Load Examples”按钮用于加载选中的图形效果对应的示例。“Quit”就是退出了。

源码

    首页的源码在 main.qml 中:

import QtQuick 2.2
import QtQuick.Window 2.1
import QtQuick.Controls 1.2

Window {
    id: appWin;
    visible: true;
    width: 640;
    height: 640;
    minimumWidth: 640;
    minimumHeight: 640;
    color: "lightgray";
    property var currentExample: null;

    Text {
        id: clue;
        text: "Graphical Effects Examples";
        anchors.top: parent.top;
        anchors.left: parent.left;
        anchors.margins: 4;
        font.pointSize: 24;
        font.bold: true;
    }

    Rectangle{
        anchors.left: clue.left;
        anchors.right: parent.right;
        anchors.rightMargin: 4;
        anchors.top: clue.bottom;
        height: 2;
        border.width: 1;
        border.color: "darkgray";
    }

    Component {
        id: exampleDelegate;
        Rectangle {
            id: wrapper;
            width: parent.width;
            height: 40;
            color: "transparent";

            Text {
                anchors.fill: parent;
                text: name;
                color: wrapper.ListView.isCurrentItem ? "blue" : "steelblue";
                font.pointSize: 20;
                verticalAlignment: Text.AlignVCenter;
            }

            MouseArea {
                anchors.fill: parent;
                onClicked: {
                    wrapper.ListView.view.currentIndex = index;
                }
            }
        }
    }

    ListView {
        id: examples;
        anchors.bottom: quit.top;
        anchors.top: clue.bottom;
        anchors.left: parent.left;
        anchors.right: parent.right;
        anchors.margins: 8;
        clip: true;
        delegate: exampleDelegate;
        highlight: Rectangle {
            color: "lightblue";
            width: parent.width;
        }
        model: ListModel {
            ListElement {
                name: "Blend";
                example: "BlendExample.qml";
            }
            ListElement {
                name: "Color";
                example: "ColorExample.qml";
            }
            ListElement {
                name: "Gradient";
                example: "GradientExample.qml";
            }
            ListElement {
                name: "Distortion";
                example: "DistortionExample.qml";
            }
            ListElement {
                name: "Drop Shadow";
                example: "DropShadowExample.qml";
            }
            ListElement {
                name: "Blur";
                example: "BlurExample.qml";
            }
            ListElement {
                name: "Motion Blur";
                example: "MotionBlurExample.qml";
            }
            ListElement {
                name: "Glow";
                example: "GlowExample.qml";
            }
            ListElement {
                name: "Mask";
                example: "MaskExample.qml";
            }
        }
    }

    Button {
        id: load;
        text: "Load Examples";
        anchors.right: quit.left;
        anchors.top: quit.top;
        anchors.rightMargin: 8;
        onClicked: {
            var data = examples.model.get(examples.currentIndex);
            console.log("example: " , data.example);

            var comp = Qt.createComponent(data.example);
            if(comp.status == Component.Ready){
                appWin.currentExample = comp.createObject(appWin, {"color" : appWin.color});
                appWin.currentExample.back.connect(appWin.closeCurrentExample);
            }
        }
    }

    Button {
        id: quit;
        text: "Quit";
        anchors.bottom: parent.bottom;
        anchors.right: parent.right;
        anchors.margins: 8;
        onClicked: Qt.quit();
    }

    function closeCurrentExample() {
        currentExample.destroy();
    }
}

    源码比较简单,从设计上解释一下。

列表视图

    ListView列出了所有的图形效果。

    exampleDelegate 这个组件用于绘制 ListView 里的一个 Item 。它接受并处理鼠标事件,改变 ListView 的当前 Item ;也改变当前 Item 的文本显示效果。

    ListModel 非常简单,只是使用 ListElement 列出了所有图形效果的名字(角色名为name)和对应的示例文档(角色名为example),在 delegate 中我们可以通过角色名访问 Model 中的数据。

    这就是 ListView 了: view + model + delegate ,非常灵活。更详细的用法,可以参考我的书《Qt Quick核心编程》,里面对 ListView 有超级详细的介绍。

动态加载图形效果

    我给每一类图形效果提供了一个单独的演示界面,在 ListModel 内, example 这个角色保存了对应的示例 QML 文档的名字。当用户点击“Load Examples”按钮时,我获取到 ListView 的当前 Item ,通过 Model 取出数据,访问 example 角色,得到实际的 QML 文档名字,然后使用 Qt.createComponent() 和 Component.createObject() 来加载 QML 文档并生成示例组件。


    好啦,这次就先介绍到这里,下一次我们介绍 混合效果

--------

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

阅读更多

没有更多推荐了,返回首页