Qt Quick裡的圖形效果:陰影(Drop Shadow),quickdrop

來源:互聯網
上載者:User

Qt Quick裡的圖形效果:陰影(Drop Shadow),quickdrop

    Qt Quick提供了兩種陰影製作效果:

  • DropShow,陰影。這個元素會根據源映像,產生一個彩色的、模糊的新映像,把這個新映像放在源映像後面,給人一種源映像從背景上凸出來的效果。
  • InnerShadow,內陰影。這個元素會根據源映像,產生一個彩色的、模糊的新映像,與 DropShadow不同的是,新映像會放在源映像裡面。

效果

    下面是我設計的樣本效果。

    首先是 DropShadow :


                       圖1 陰影製作效果

    然後是內陰影製作效果:


                    圖2 內陰影製作效果

源碼分析

    1所示,介面被分為三部分。

    最上面的是源映像。

    源映像下面(即中間)是一個列表,你可以點擊 DropShadow 和 InnerShadow 兩個子項,切換不同的陰影製作效果。每種陰影製作效果都對應一個 qml 文檔,當你點擊這些子項時,對應的 qml 文檔動態載入。

陰影樣本介面

    這個樣本介面架構其實與“Qt Quick裡的圖形效果——顏色(Color)”是一致的,只是我把 ListView 從原來的豎向改為了橫向。對應的 DropShadowExample.qml 內容如下:

import QtQuick 2.2import QtQuick.Controls 1.2Rectangle {    id: example;    signal back();    anchors.fill: parent;    Text {        id: origLabel;        x: 10;        y: 4;        font.pointSize: 20;        text: "Original Image";    }    Button {        anchors.right: parent.right;        anchors.top: parent.top;        anchors.margins: 4;        text: "Back";        onClicked: example.back();    }    Image {        id: origImage;        width: 240;        height: 240;        anchors.left: parent.left;        anchors.top: origLabel.bottom;        anchors.margins: 4;        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: origImage.bottom;        height: 2;        border.width: 1;        border.color: "darkgray";    }    Text {        id: effectsLabel;        anchors.top: origImage.bottom;        anchors.margins: 4;        anchors.left: parent.left;        font.pointSize: 20;        font.bold: true;        text: "Shadow Effects:";        color: "blue";    }    Rectangle {        id: shadowEffects;        anchors.left: effectsLabel.right;        anchors.leftMargin: 4;        anchors.top: effectsLabel.top;        anchors.right: parent.right;        anchors.rightMargin: 4;        height: 40;        color: "gray";        ListView {            anchors.fill: parent;            clip: true;            focus: true;            orientation: ListView.Horizontal;            spacing: 20;            delegate: Text {                id: wrapper;                height: 40;                verticalAlignment: Text.AlignVCenter;                text: name;                font.pointSize: 18;                Keys.onEnterPressed: {                    event.accepted = true;                    effectControl.source = example;                }                Keys.onReturnPressed: {                    event.accepted = true;                    effectControl.source = example;                }                MouseArea {                    anchors.fill: parent;                    onClicked: {                        wrapper.ListView.view.currentIndex = index;                        effectControl.source = example;                    }                }            }            highlight: Rectangle {                height: parent.height;                color: "lightblue";            }            model: shadowsModel;        }    }    Loader {        id: effectControl;        anchors.top: shadowEffects.bottom;        anchors.left: parent.left;        anchors.bottom: parent.bottom;        anchors.right: parent.right;        anchors.margins: 4;        source: "DropShadowEx.qml";    }    ListModel {        id: shadowsModel;        ListElement {            name: "DropShadow";            example: "DropShadowEx.qml";        }        ListElement {            name: "InnerShadow";            example: "InnerShadowEx.qml";        }    }}

    DropShawExample.qml 會被“Qt Quick裡的圖形效果(Graphical Effects)”裡介紹過的 main.qml 動態載入。

陰影製作效果

    陰影製作效果對應的 DropShadowEx.qml 內容如下:

import QtQuick 2.2import QtGraphicalEffects 1.0import QtQuick.Controls 1.2Rectangle {    anchors.fill: parent;    Image {        id: opImage;        x: 4;        y: 4;        width: 250;        height: 250;        source: "butterfly.png";        sourceSize: Qt.size(250, 250);        smooth: true;        visible: false;    }    DropShadow {        id: dropshadow;        anchors.fill: opImage;        source: opImage;    }    Rectangle {        anchors.left: opImage.right;        anchors.top: opImage.top;        anchors.right: parent.right;        anchors.bottom: parent.bottom;        anchors.margins: 2;        color: "lightsteelblue";        CheckBox {            id: fast;            anchors.top: parent.top;            anchors.topMargin: 4;            anchors.left: parent.left;            anchors.leftMargin: 4;            checked: false;            text: "fast";        }        CheckBox {            id: transparentBorder;            anchors.left: fast.right;            anchors.leftMargin: 8;            anchors.top: fast.top;            checked: false;            text: "transparentBorder";        }        Text {            id: colorLabel;            anchors.left: fast.left;            anchors.top: fast.bottom;            anchors.topMargin: 8;            text: "shadow color:";        }        ColorPicker {            id: shadowColor;            anchors.left: colorLabel.right;            anchors.leftMargin: 4;            anchors.top: colorLabel.top;            width: 90;            height: 28;            color: "#ff000000";        }        Text {            id: sampleLabel;            anchors.left: fast.left;            anchors.top: shadowColor.bottom;            anchors.topMargin: 8;            text: "samples:";        }        Slider {            id: sampleSlider;            anchors.left: sampleLabel.right;            anchors.leftMargin: 4;            anchors.top: sampleLabel.top;            minimumValue: 0;            maximumValue: 32;            value: 0.0;            width: 160;            height: 30;            stepSize: 1.0;        }        Text {            id: spreadLabel;            anchors.left: fast.left;            anchors.top: sampleSlider.bottom;            anchors.topMargin: 8;            text: "spread:";        }        Slider {            id: spreadSlider;            anchors.left: spreadLabel.right;            anchors.leftMargin: 4;            anchors.top: spreadLabel.top;            value: 0.5;            width: 160;            height: 30;        }        Text {            id: radiusLabel;            anchors.left: fast.left;            anchors.top: spreadSlider.bottom;            anchors.topMargin: 8;            text: "radius:";        }        Rectangle {            id: radiusArea;            anchors.left: radiusLabel.right;            anchors.leftMargin: 4;            anchors.top: radiusLabel.top;            height: 30;            width: 160;            color: "lightgray";            border.width: 1;            border.color: "darkgray";            TextInput {                anchors.fill: parent;                anchors.margins: 2;                id: radiusEdit;                font.pointSize: 18;                text: "0.0";                validator: DoubleValidator{bottom: 0;}            }        }        Text {            id: voffLabel;            anchors.left: fast.left;            anchors.top: radiusArea.bottom;            anchors.topMargin: 8;            text: "verticalOffset:";        }        Rectangle {            id: voffArea;            anchors.left: voffLabel.right;            anchors.leftMargin: 4;            anchors.top: voffLabel.top;            height: 30;            width: 160;            color: "lightgray";            border.width: 1;            border.color: "darkgray";            TextInput {                anchors.fill: parent;                anchors.margins: 2;                id: voffEdit;                font.pointSize: 18;                text: "0.0";                validator: DoubleValidator{}            }        }        Text {            id: hoffLabel;            anchors.left: fast.left;            anchors.top: voffArea.bottom;            anchors.topMargin: 8;            text: "horizontalOffset:";        }        Rectangle {            id: hoffArea;            anchors.left: hoffLabel.right;            anchors.leftMargin: 4;            anchors.top: hoffLabel.top;            height: 30;            width: 160;            color: "lightgray";            border.width: 1;            border.color: "darkgray";            TextInput {                anchors.fill: parent;                anchors.margins: 2;                id: hoffEdit;                font.pointSize: 18;                text: "0.0";                validator: DoubleValidator{}            }        }        Button {            id: applyBtn;            anchors.left: parent.left;            anchors.leftMargin: 4;            anchors.top: hoffArea.bottom;            anchors.topMargin: 12;            text: "Apply";            onClicked: {                dropshadow.color = shadowColor.color;                dropshadow.fast = fast.checked;                dropshadow.transparentBorder = transparentBorder.checked;                dropshadow.samples = sampleSlider.value;                dropshadow.radius = parseFloat(radiusEdit.text);                dropshadow.verticalOffset = voffEdit.text;                dropshadow.horizontalOffset = hoffEdit.text;                dropshadow.spread = spreadSlider.value;            }        }    }}

    代碼比較簡單,不細說了。我們看看 DropShadow 元素的各個屬性都什麼含義吧。

  • source,variant類型,指向源Item
  • horizontalOffset 與verticalOffset,real類型,指定陰影相對於源Item的水平和垂直位移量,預設為 0 
  • radius,real類型,設定陰影的柔和程度,值越大,陰影的邊緣就會顯得越柔和
  • sample,int類型,指定產生陰影時陰影的每個像素由多少個採樣點產生,採樣點越多陰影製作效果越好,不過也越慢。一般可以把這個值設定為 radius的2倍。
  • spread,real類型,指定如何強化陰影接近源 Item 邊緣的部分,取值範圍為 0.0 -- 1.0 ,預設為 0.5

    未提及的屬性都比較簡單,想 cached 、 fast 、 transparentBorder 等,之前的文章也提到過。

內陰影

    內陰影製作效果對應的 InnerShadowEx.qml 內容如下:

import QtQuick 2.2import QtGraphicalEffects 1.0import QtQuick.Controls 1.2Rectangle {    anchors.fill: parent;    Image {        id: opImage;        x: 4;        y: 4;        width: 250;        height: 250;        source: "butterfly.png";        sourceSize: Qt.size(250, 250);        smooth: true;        visible: false;    }    InnerShadow {        id: innershadow;        anchors.fill: opImage;        source: opImage;    }    Rectangle {        anchors.left: opImage.right;        anchors.top: opImage.top;        anchors.right: parent.right;        anchors.bottom: parent.bottom;        anchors.margins: 2;        color: "lightsteelblue";        CheckBox {            id: fast;            anchors.top: parent.top;            anchors.topMargin: 4;            anchors.left: parent.left;            anchors.leftMargin: 4;            checked: false;            text: "fast";        }        Text {            id: colorLabel;            anchors.left: fast.left;            anchors.top: fast.bottom;            anchors.topMargin: 8;            text: "shadow color:";        }        ColorPicker {            id: shadowColor;            anchors.left: colorLabel.right;            anchors.leftMargin: 4;            anchors.top: colorLabel.top;            width: 90;            height: 28;            color: "#ff000000";        }        Text {            id: sampleLabel;            anchors.left: fast.left;            anchors.top: shadowColor.bottom;            anchors.topMargin: 8;            text: "samples:";        }        Slider {            id: sampleSlider;            anchors.left: sampleLabel.right;            anchors.leftMargin: 4;            anchors.top: sampleLabel.top;            minimumValue: 0;            maximumValue: 32;            value: 0.0;            width: 160;            height: 30;            stepSize: 1.0;        }        Text {            id: spreadLabel;            anchors.left: fast.left;            anchors.top: sampleSlider.bottom;            anchors.topMargin: 8;            text: "spread:";        }        Slider {            id: spreadSlider;            anchors.left: spreadLabel.right;            anchors.leftMargin: 4;            anchors.top: spreadLabel.top;            value: 0.5;            width: 160;            height: 30;        }        Text {            id: radiusLabel;            anchors.left: fast.left;            anchors.top: spreadSlider.bottom;            anchors.topMargin: 8;            text: "radius:";        }        Rectangle {            id: radiusArea;            anchors.left: radiusLabel.right;            anchors.leftMargin: 4;            anchors.top: radiusLabel.top;            height: 30;            width: 160;            color: "lightgray";            border.width: 1;            border.color: "darkgray";            TextInput {                anchors.fill: parent;                anchors.margins: 2;                id: radiusEdit;                font.pointSize: 18;                text: "0.0";                validator: DoubleValidator{bottom: 0;}            }        }        Text {            id: voffLabel;            anchors.left: fast.left;            anchors.top: radiusArea.bottom;            anchors.topMargin: 8;            text: "verticalOffset:";        }        Rectangle {            id: voffArea;            anchors.left: voffLabel.right;            anchors.leftMargin: 4;            anchors.top: voffLabel.top;            height: 30;            width: 160;            color: "lightgray";            border.width: 1;            border.color: "darkgray";            TextInput {                anchors.fill: parent;                anchors.margins: 2;                id: voffEdit;                font.pointSize: 18;                text: "0.0";                validator: DoubleValidator{}            }        }        Text {            id: hoffLabel;            anchors.left: fast.left;            anchors.top: voffArea.bottom;            anchors.topMargin: 8;            text: "verticalOffset:";        }        Rectangle {            id: hoffArea;            anchors.left: hoffLabel.right;            anchors.leftMargin: 4;            anchors.top: hoffLabel.top;            height: 30;            width: 160;            color: "lightgray";            border.width: 1;            border.color: "darkgray";            TextInput {                anchors.fill: parent;                anchors.margins: 2;                id: hoffEdit;                font.pointSize: 18;                text: "0.0";                validator: DoubleValidator{}            }        }        Button {            id: applyBtn;            anchors.left: parent.left;            anchors.leftMargin: 4;            anchors.top: hoffArea.bottom;            anchors.topMargin: 12;            text: "Apply";            onClicked: {                innershadow.color = shadowColor.color;                innershadow.fast = fast.checked;                innershadow.samples = sampleSlider.value;                innershadow.radius = parseFloat(radiusEdit.text);                innershadow.verticalOffset = voffEdit.text;                innershadow.horizontalOffset = hoffEdit.text;                innershadow.spread = spreadSlider.value;            }        }    }}

    源碼比較簡單,不說了。

    InnerShadow 比 DropShadow 少了一個 transparentBorder 屬性,其他基本一致,偷個懶,也不說了。


    回顧一下:

  • Qt Quick裡的圖形效果——漸層(Gradient)
  • Qt Quick裡的圖形效果——顏色(Color)
  • Qt Quick裡的圖形效果——混合(Blend)
  • Qt Quick裡的圖形效果(Graphical Effects)
  • Qt Quick專欄

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.