Qt Quick提供了两种阴影效果:

  • DropShow,阴影。这个元素会根据源图像,产生一个彩色的、模糊的新图像,把这个新图像放在源图像后面,给人一种源图像从背景上凸出来的效果。
  • InnerShadow,内阴影。这个元素会根据源图像,产生一个彩色的、模糊的新图像,与 DropShadow不同的是,新图像会放在源图像里面。

效果

下面是我设计的示例效果。

首先是 DropShadow :

图1 阴影效果

然后是内阴影效果:

图2 内阴影效果

源码分析

如图1所示,界面被分为三部分。

最上面的是源图像。

源图像下面(即中间)是一个列表,你可以点击 DropShadow 和 InnerShadow 两个子项,切换不同的阴影效果。每种阴影效果都对应一个 qml 文档,当你点击这些子项时,对应的 qml 文档动态加载。

阴影示例界面

这个示例界面框架其实与“Qt Quick里的图形效果——颜色(Color)”是一致的,只是我把 ListView 从原来的竖向改为了横向。对应的 DropShadowExample.qml 内容如下:

  1. import QtQuick 2.2
  2. import QtQuick.Controls 1.2
  3. Rectangle {
  4. id: example;
  5. signal back();
  6. anchors.fill: parent;
  7. Text {
  8. id: origLabel;
  9. x: 10;
  10. y: 4;
  11. font.pointSize: 20;
  12. text: "Original Image";
  13. }
  14. Button {
  15. anchors.right: parent.right;
  16. anchors.top: parent.top;
  17. anchors.margins: 4;
  18. text: "Back";
  19. onClicked: example.back();
  20. }
  21. Image {
  22. id: origImage;
  23. width: 240;
  24. height: 240;
  25. anchors.left: parent.left;
  26. anchors.top: origLabel.bottom;
  27. anchors.margins: 4;
  28. source: "butterfly.png";
  29. sourceSize: Qt.size(240, 240);
  30. smooth: true;
  31. }
  32. Rectangle{
  33. anchors.left: parent.left;
  34. anchors.leftMargin: 4;
  35. anchors.right: parent.right;
  36. anchors.rightMargin: 4;
  37. anchors.top: origImage.bottom;
  38. height: 2;
  39. border.width: 1;
  40. border.color: "darkgray";
  41. }
  42. Text {
  43. id: effectsLabel;
  44. anchors.top: origImage.bottom;
  45. anchors.margins: 4;
  46. anchors.left: parent.left;
  47. font.pointSize: 20;
  48. font.bold: true;
  49. text: "Shadow Effects:";
  50. color: "blue";
  51. }
  52. Rectangle {
  53. id: shadowEffects;
  54. anchors.left: effectsLabel.right;
  55. anchors.leftMargin: 4;
  56. anchors.top: effectsLabel.top;
  57. anchors.right: parent.right;
  58. anchors.rightMargin: 4;
  59. height: 40;
  60. color: "gray";
  61. ListView {
  62. anchors.fill: parent;
  63. clip: true;
  64. focus: true;
  65. orientation: ListView.Horizontal;
  66. spacing: 20;
  67. delegate: Text {
  68. id: wrapper;
  69. height: 40;
  70. verticalAlignment: Text.AlignVCenter;
  71. text: name;
  72. font.pointSize: 18;
  73. Keys.onEnterPressed: {
  74. event.accepted = true;
  75. effectControl.source = example;
  76. }
  77. Keys.onReturnPressed: {
  78. event.accepted = true;
  79. effectControl.source = example;
  80. }
  81. MouseArea {
  82. anchors.fill: parent;
  83. onClicked: {
  84. wrapper.ListView.view.currentIndex = index;
  85. effectControl.source = example;
  86. }
  87. }
  88. }
  89. highlight: Rectangle {
  90. height: parent.height;
  91. color: "lightblue";
  92. }
  93. model: shadowsModel;
  94. }
  95. }
  96. Loader {
  97. id: effectControl;
  98. anchors.top: shadowEffects.bottom;
  99. anchors.left: parent.left;
  100. anchors.bottom: parent.bottom;
  101. anchors.right: parent.right;
  102. anchors.margins: 4;
  103. source: "DropShadowEx.qml";
  104. }
  105. ListModel {
  106. id: shadowsModel;
  107. ListElement {
  108. name: "DropShadow";
  109. example: "DropShadowEx.qml";
  110. }
  111. ListElement {
  112. name: "InnerShadow";
  113. example: "InnerShadowEx.qml";
  114. }
  115. }
  116. }

DropShawExample.qml 会被“Qt Quick里的图形效果(Graphical Effects)”里介绍过的 main.qml 动态加载。

阴影效果

阴影效果对应的 DropShadowEx.qml 内容如下:

  1. import QtQuick 2.2
  2. import QtGraphicalEffects 1.0
  3. import QtQuick.Controls 1.2
  4. Rectangle {
  5. anchors.fill: parent;
  6. Image {
  7. id: opImage;
  8. x: 4;
  9. y: 4;
  10. width: 250;
  11. height: 250;
  12. source: "butterfly.png";
  13. sourceSize: Qt.size(250, 250);
  14. smooth: true;
  15. visible: false;
  16. }
  17. DropShadow {
  18. id: dropshadow;
  19. anchors.fill: opImage;
  20. source: opImage;
  21. }
  22. Rectangle {
  23. anchors.left: opImage.right;
  24. anchors.top: opImage.top;
  25. anchors.right: parent.right;
  26. anchors.bottom: parent.bottom;
  27. anchors.margins: 2;
  28. color: "lightsteelblue";
  29. CheckBox {
  30. id: fast;
  31. anchors.top: parent.top;
  32. anchors.topMargin: 4;
  33. anchors.left: parent.left;
  34. anchors.leftMargin: 4;
  35. checked: false;
  36. text: "fast";
  37. }
  38. CheckBox {
  39. id: transparentBorder;
  40. anchors.left: fast.right;
  41. anchors.leftMargin: 8;
  42. anchors.top: fast.top;
  43. checked: false;
  44. text: "transparentBorder";
  45. }
  46. Text {
  47. id: colorLabel;
  48. anchors.left: fast.left;
  49. anchors.top: fast.bottom;
  50. anchors.topMargin: 8;
  51. text: "shadow color:";
  52. }
  53. ColorPicker {
  54. id: shadowColor;
  55. anchors.left: colorLabel.right;
  56. anchors.leftMargin: 4;
  57. anchors.top: colorLabel.top;
  58. width: 90;
  59. height: 28;
  60. color: "#ff000000";
  61. }
  62. Text {
  63. id: sampleLabel;
  64. anchors.left: fast.left;
  65. anchors.top: shadowColor.bottom;
  66. anchors.topMargin: 8;
  67. text: "samples:";
  68. }
  69. Slider {
  70. id: sampleSlider;
  71. anchors.left: sampleLabel.right;
  72. anchors.leftMargin: 4;
  73. anchors.top: sampleLabel.top;
  74. minimumValue: 0;
  75. maximumValue: 32;
  76. value: 0.0;
  77. width: 160;
  78. height: 30;
  79. stepSize: 1.0;
  80. }
  81. Text {
  82. id: spreadLabel;
  83. anchors.left: fast.left;
  84. anchors.top: sampleSlider.bottom;
  85. anchors.topMargin: 8;
  86. text: "spread:";
  87. }
  88. Slider {
  89. id: spreadSlider;
  90. anchors.left: spreadLabel.right;
  91. anchors.leftMargin: 4;
  92. anchors.top: spreadLabel.top;
  93. value: 0.5;
  94. width: 160;
  95. height: 30;
  96. }
  97. Text {
  98. id: radiusLabel;
  99. anchors.left: fast.left;
  100. anchors.top: spreadSlider.bottom;
  101. anchors.topMargin: 8;
  102. text: "radius:";
  103. }
  104. Rectangle {
  105. id: radiusArea;
  106. anchors.left: radiusLabel.right;
  107. anchors.leftMargin: 4;
  108. anchors.top: radiusLabel.top;
  109. height: 30;
  110. width: 160;
  111. color: "lightgray";
  112. border.width: 1;
  113. border.color: "darkgray";
  114. TextInput {
  115. anchors.fill: parent;
  116. anchors.margins: 2;
  117. id: radiusEdit;
  118. font.pointSize: 18;
  119. text: "0.0";
  120. validator: DoubleValidator{bottom: 0;}
  121. }
  122. }
  123. Text {
  124. id: voffLabel;
  125. anchors.left: fast.left;
  126. anchors.top: radiusArea.bottom;
  127. anchors.topMargin: 8;
  128. text: "verticalOffset:";
  129. }
  130. Rectangle {
  131. id: voffArea;
  132. anchors.left: voffLabel.right;
  133. anchors.leftMargin: 4;
  134. anchors.top: voffLabel.top;
  135. height: 30;
  136. width: 160;
  137. color: "lightgray";
  138. border.width: 1;
  139. border.color: "darkgray";
  140. TextInput {
  141. anchors.fill: parent;
  142. anchors.margins: 2;
  143. id: voffEdit;
  144. font.pointSize: 18;
  145. text: "0.0";
  146. validator: DoubleValidator{}
  147. }
  148. }
  149. Text {
  150. id: hoffLabel;
  151. anchors.left: fast.left;
  152. anchors.top: voffArea.bottom;
  153. anchors.topMargin: 8;
  154. text: "horizontalOffset:";
  155. }
  156. Rectangle {
  157. id: hoffArea;
  158. anchors.left: hoffLabel.right;
  159. anchors.leftMargin: 4;
  160. anchors.top: hoffLabel.top;
  161. height: 30;
  162. width: 160;
  163. color: "lightgray";
  164. border.width: 1;
  165. border.color: "darkgray";
  166. TextInput {
  167. anchors.fill: parent;
  168. anchors.margins: 2;
  169. id: hoffEdit;
  170. font.pointSize: 18;
  171. text: "0.0";
  172. validator: DoubleValidator{}
  173. }
  174. }
  175. Button {
  176. id: applyBtn;
  177. anchors.left: parent.left;
  178. anchors.leftMargin: 4;
  179. anchors.top: hoffArea.bottom;
  180. anchors.topMargin: 12;
  181. text: "Apply";
  182. onClicked: {
  183. dropshadow.color = shadowColor.color;
  184. dropshadow.fast = fast.checked;
  185. dropshadow.transparentBorder = transparentBorder.checked;
  186. dropshadow.samples = sampleSlider.value;
  187. dropshadow.radius = parseFloat(radiusEdit.text);
  188. dropshadow.verticalOffset = voffEdit.text;
  189. dropshadow.horizontalOffset = hoffEdit.text;
  190. dropshadow.spread = spreadSlider.value;
  191. }
  192. }
  193. }
  194. }

代码比较简单,不细说了。我们看看 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 内容如下:

  1. import QtQuick 2.2
  2. import QtGraphicalEffects 1.0
  3. import QtQuick.Controls 1.2
  4. Rectangle {
  5. anchors.fill: parent;
  6. Image {
  7. id: opImage;
  8. x: 4;
  9. y: 4;
  10. width: 250;
  11. height: 250;
  12. source: "butterfly.png";
  13. sourceSize: Qt.size(250, 250);
  14. smooth: true;
  15. visible: false;
  16. }
  17. InnerShadow {
  18. id: innershadow;
  19. anchors.fill: opImage;
  20. source: opImage;
  21. }
  22. Rectangle {
  23. anchors.left: opImage.right;
  24. anchors.top: opImage.top;
  25. anchors.right: parent.right;
  26. anchors.bottom: parent.bottom;
  27. anchors.margins: 2;
  28. color: "lightsteelblue";
  29. CheckBox {
  30. id: fast;
  31. anchors.top: parent.top;
  32. anchors.topMargin: 4;
  33. anchors.left: parent.left;
  34. anchors.leftMargin: 4;
  35. checked: false;
  36. text: "fast";
  37. }
  38. Text {
  39. id: colorLabel;
  40. anchors.left: fast.left;
  41. anchors.top: fast.bottom;
  42. anchors.topMargin: 8;
  43. text: "shadow color:";
  44. }
  45. ColorPicker {
  46. id: shadowColor;
  47. anchors.left: colorLabel.right;
  48. anchors.leftMargin: 4;
  49. anchors.top: colorLabel.top;
  50. width: 90;
  51. height: 28;
  52. color: "#ff000000";
  53. }
  54. Text {
  55. id: sampleLabel;
  56. anchors.left: fast.left;
  57. anchors.top: shadowColor.bottom;
  58. anchors.topMargin: 8;
  59. text: "samples:";
  60. }
  61. Slider {
  62. id: sampleSlider;
  63. anchors.left: sampleLabel.right;
  64. anchors.leftMargin: 4;
  65. anchors.top: sampleLabel.top;
  66. minimumValue: 0;
  67. maximumValue: 32;
  68. value: 0.0;
  69. width: 160;
  70. height: 30;
  71. stepSize: 1.0;
  72. }
  73. Text {
  74. id: spreadLabel;
  75. anchors.left: fast.left;
  76. anchors.top: sampleSlider.bottom;
  77. anchors.topMargin: 8;
  78. text: "spread:";
  79. }
  80. Slider {
  81. id: spreadSlider;
  82. anchors.left: spreadLabel.right;
  83. anchors.leftMargin: 4;
  84. anchors.top: spreadLabel.top;
  85. value: 0.5;
  86. width: 160;
  87. height: 30;
  88. }
  89. Text {
  90. id: radiusLabel;
  91. anchors.left: fast.left;
  92. anchors.top: spreadSlider.bottom;
  93. anchors.topMargin: 8;
  94. text: "radius:";
  95. }
  96. Rectangle {
  97. id: radiusArea;
  98. anchors.left: radiusLabel.right;
  99. anchors.leftMargin: 4;
  100. anchors.top: radiusLabel.top;
  101. height: 30;
  102. width: 160;
  103. color: "lightgray";
  104. border.width: 1;
  105. border.color: "darkgray";
  106. TextInput {
  107. anchors.fill: parent;
  108. anchors.margins: 2;
  109. id: radiusEdit;
  110. font.pointSize: 18;
  111. text: "0.0";
  112. validator: DoubleValidator{bottom: 0;}
  113. }
  114. }
  115. Text {
  116. id: voffLabel;
  117. anchors.left: fast.left;
  118. anchors.top: radiusArea.bottom;
  119. anchors.topMargin: 8;
  120. text: "verticalOffset:";
  121. }
  122. Rectangle {
  123. id: voffArea;
  124. anchors.left: voffLabel.right;
  125. anchors.leftMargin: 4;
  126. anchors.top: voffLabel.top;
  127. height: 30;
  128. width: 160;
  129. color: "lightgray";
  130. border.width: 1;
  131. border.color: "darkgray";
  132. TextInput {
  133. anchors.fill: parent;
  134. anchors.margins: 2;
  135. id: voffEdit;
  136. font.pointSize: 18;
  137. text: "0.0";
  138. validator: DoubleValidator{}
  139. }
  140. }
  141. Text {
  142. id: hoffLabel;
  143. anchors.left: fast.left;
  144. anchors.top: voffArea.bottom;
  145. anchors.topMargin: 8;
  146. text: "verticalOffset:";
  147. }
  148. Rectangle {
  149. id: hoffArea;
  150. anchors.left: hoffLabel.right;
  151. anchors.leftMargin: 4;
  152. anchors.top: hoffLabel.top;
  153. height: 30;
  154. width: 160;
  155. color: "lightgray";
  156. border.width: 1;
  157. border.color: "darkgray";
  158. TextInput {
  159. anchors.fill: parent;
  160. anchors.margins: 2;
  161. id: hoffEdit;
  162. font.pointSize: 18;
  163. text: "0.0";
  164. validator: DoubleValidator{}
  165. }
  166. }
  167. Button {
  168. id: applyBtn;
  169. anchors.left: parent.left;
  170. anchors.leftMargin: 4;
  171. anchors.top: hoffArea.bottom;
  172. anchors.topMargin: 12;
  173. text: "Apply";
  174. onClicked: {
  175. innershadow.color = shadowColor.color;
  176. innershadow.fast = fast.checked;
  177. innershadow.samples = sampleSlider.value;
  178. innershadow.radius = parseFloat(radiusEdit.text);
  179. innershadow.verticalOffset = voffEdit.text;
  180. innershadow.horizontalOffset = hoffEdit.text;
  181. innershadow.spread = spreadSlider.value;
  182. }
  183. }
  184. }
  185. }

源码比较简单,不说了。

InnerShadow 比 DropShadow 少了一个 transparentBorder 属性,其他基本一致,偷个懒,也不说了。

回顾一下:

Qt Quick里的图形效果:阴影(Drop Shadow)的更多相关文章

  1. Qt Quick实现的疯狂算数游戏

    使用 Qt Quick 写了个小游戏:疯狂算数.支持 Windows 和 Android 两个平台. 游戏简单,但牵涉到下面你的 Qt Quick 主题: 自己实现一个按钮 自适应分辨率 国际化 QM ...

  2. Qt Quick实现的涂鸦程序

    之前一直以为 Qt Quick 里 Canvas 才干够自绘.后来发觉不是,原来还有好几种方式都能够画图! 能够使用原始的 OpenGL(Qt Quick 使用 OpenGL 渲染).能够构造QSGN ...

  3. Qt Quick之StackView具体解释(1)

    Qt Quick中有个StackView.我在<Qt Quick核心编程>一书中没有讲到.近期有人问起,趁机学习了一下,把它的基本使用方法记录下来. 我准备分两次来讲.第一次讲主要的使用方 ...

  4. Qt Quick综合实例之文件查看器

    假设你基于Qt SDK 5.3.1来创建一个Qt Quick App项目,项目模板为你准备的main.qml文档的根元素是ApplicationWindow或Window.这次我们就以Applicat ...

  5. 《Qt Quick 4小时入门》学习笔记

    http://edu.csdn.net/course/detail/1042/14804?auto_start=1   Qt Quick 4小时入门 第五章:Qt Quick里的信号与槽   QML中 ...

  6. Qt5官方demo分析集11——Qt Quick Particles Examples - Affectors

    在这个系列中的所有文章都可以在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873 接上文Qt5官方demo解析集10--Qt ...

  7. Qt Widgets、QML、Qt Quick的区别

    Qt Widgets.QML.Qt Quick的区别 简述 看了之前关于 QML 的一些介绍,很多人难免会有一些疑惑: Q1:QML 和 Qt Quick 之间有什么区别? Q2:QtQuick 1. ...

  8. 浏览器上的Qt Quick

    你想不想在浏览器上运行你的Qt Quick程序呢?在Qt 5.12之前,唯一的方法是使用Qt WebGL Streaming技术把界面镜像到浏览器上.但该方法有不少缺陷,下文会说.前不久随着Qt 5. ...

  9. Qt on Android: Qt Quick 之 Hello World 图文具体解释

    在上一篇文章,<Qt on Android:QML 语言基础>中,我们介绍了 QML 语言的语法,在最后我们遗留了一些问题没有展开,这篇呢,我们就正式開始撰写 Qt Quick 程序,而那 ...

随机推荐

  1. openstack私有云布署实践【12.2 网络Neutron-controller节点配置(办公网环境)】

    网络这一块推荐使用的是 Neutron--LinuxBirdge的Ha高可用,此高可用方案对Public作用不是很大,Public只用到DHCP,而Private则会用到L3 Agent,则此方案是有 ...

  2. linux安装gcc-c++

    首先查看系统是否安装: gcc -v    g++ -v    c++ -v 没有安装则执行一键安装命令:#yum install gcc-c++ 如果直接执行:#yum install c++是安装 ...

  3. [妙味JS基础]第四课:JS数据类型、类型转换

    知识点总结 JS数据类型:number数字(NaN).string字符串.boolean布尔值.函数类型.object对象(obj.[].{}.null).undefined未定义 typeof 用来 ...

  4. input输入框只允许输入数字/ 数字+小数点/ 文字+字母/ 等解决方法

    1.只允许输入数字: <input type="text" onkeyup="this.value=this.value.replace(/[^0-9]/g,'') ...

  5. offsetWidth,offsetHeight到底该如何理解?

    1.对象的可见宽度(对象指body.div等) 2.offsetWidth可以返回div的宽 3.offsetWidth=width+padding+border(不包括margin外边距) 4.返回 ...

  6. MySQL字符串类型

    VARCHAR类型用于存储变长字符串,它会删除末尾的所有空格,它比定长字符串更省空间,因为它仅使用必要的空间(越短的字符串占用越少),VARCHAR会用1或2个额外字节记录字符串长度(如果字符串长度不 ...

  7. PHP文本路径转换为链接文字

    <?php /** * 文本路径转换为有链接的文字 * @param string $str 转换内容 * @return string */ function urlToLink($str) ...

  8. 2016NEFU集训第n+5场 A - Chinese Girls' Amusement

    Description       You must have heard that the Chinese culture is quite different from that of Europ ...

  9. Business Intelligence(BI) 商务智能

    商业智能技术正是一种能够帮助企业迅速地完成信息采集.分析的先进技术.它以数据仓库(Data Warehousing).在线分析处理(OLAP).数据挖掘(Data Mining)3种技术的整合为基础, ...

  10. LINQ的Any() 方法

    Enumerable.Any 方法 确定序列中的任何元素是否存在或满足条件.