使用Qt Quick实现炫酷Cover Flow效果

 
 
使用Qt Quick实现炫酷Cover Flow效果
2017-2-6 01:20| 发布者: yafeilinux| 查看: 8253| 评论: 0|原作者: yafeilinux
 
Qt开源社区 门户 精品文章 精品教程 查看内容
摘要 : 作为社区公众号的第一篇技术文章,想了好久都没确定要写些什么,本来想写Qt编程快速入门Qt 5版第一篇的,因为这个系列教程好久没有更新了,而且很多网友都使用Qt 5学习老版本的教程,错误百出,现在作为第一篇更新出 ...
 

导语

 

    作为社区公众号的第一篇技术文章,想了好久都没确定要写些什么,本来想写Qt编程快速入门Qt 5版第一篇的,因为这个系列教程好久没有更新了,而且很多网友都使用Qt 5学习老版本的教程,错误百出,现在作为第一篇更新出来也挺好的。但是转念一想,这个教程需要和老版教程相对应,第一篇需要写安装步骤什么的啊,那作为咱们这么有意义的第一篇文章实在是说不过去。所以,最后把压箱底的这个Cover Flow拿了出来,这个最早想写在《Qt 5编程入门》中的,但是不符合那本书只讲基础知识点的原则,所以就保留下来,后面会作为一个功能模块用在《QtQt Quick开发实战精解》第2版的实例中。大家可能会说,这个效果做的真的那么好,遮遮掩掩地不早放出来,呵呵,自我感觉已经达到了理想水平,先来看下效果吧!

 

 

 

开发环境

 

Win 7 + Qt 5.8.0

 

 

实现功能

 

    如果大家了解过QML和Qt Quick,那么一定会想到这个需要使用PathView来实现。没错,这个效果是使用PathView实现的,而且如果学习过《Qt 5编程入门》,那么实现这个功能应该不难,但是难点在于动画的处理以及那个倒影的实现。再美好的东西都是从最基本的框架完善出来的,所以,我们先从实现基本功能讲起。

    首先创建一个Qt Quick Application,然后将main.qml中的Window定义如下:

Window{

   visible:true

   width:1100; height:900

 

   ListModel{

       id:model

       ListElement{url:"qrc:/images/01.png"}

       ListElement{url:"qrc:/images/02.png"}

       ListElement{url:"qrc:/images/03.png"}

       ListElement{url:"qrc:/images/04.png"}

       ListElement{url:"qrc:/images/05.png"}

   }

 

   CoverFlow{

       anchors.fill:parent

       model:model

   }

}

       这里主要是创建了视图和模型,视图就是CoverFlow,这个使用单独文件来定义,模型中提供了5张图片,大家可以找一些漂亮的图片,然后新建一个资源文件,把它们放进去。下面重点来看下CoverFlow文件,向资源文件qml.qrc中添加新的QML File,名称设置为CoverFlow,完成后,将其中Item定义修改如下:

Item{

    id:coverFlow

 

    property ListModel model

    property int itemCount:5

 

    PathView{

       id:pathView

 

       model:coverFlow.model

       delegate:MyDelegate{}

       path:coverFlowPath

       pathItemCount:coverFlow.itemCount

       anchors.fill:parent

    }

 

    Path{

       id:coverFlowPath

       startX:0

       startY:coverFlow.height/3

 

       PathLine{x:coverFlow.width*0.5;y:coverFlow.height/3;  }

       PathPercent{value:0.50}

 

       PathLine{x:coverFlow.width;y:coverFlow.height/3;}

       PathPercent{value:1.0}

    }

}

       这里是最简单最标准的PathView的应用,设置了模型、委托以及路径,路径只是简单地进行了三等分。下面再向qml.qrc中添加一个MyDelegate.qml文件作为委托,修改其Item如下:

Item{

    id:delegateItem

    width:320

    height:450

 

    Image{

       id:dlgImg

       source:url

    }

}

       这里也非常简单,指定了数据模型中每个条目都以图片形式显示,并设置了图片的大小。到这里基本功能已经实现了,简简单单数十行代码,现在运行程序,效果是这样的:

 

 

 

完善效果

 

    为了实现应有的CoverFlow效果,现在对程序进行优化。最能使效果产生变化的就是修改路径:

Path{

    id:coverFlowPath

    startX:0

    startY:coverFlow.height/3

    PathAttribute{name:"iconZ";value:0}

    PathAttribute{name:"iconAngle";value:70}

    PathAttribute{name:"iconScale";value:0.6}

 

    PathLine{x:coverFlow.width*0.5;y:coverFlow.height/3;  }

    PathAttribute{name:"iconZ";value:100}

    PathAttribute{name:"iconAngle";value:0}

    PathAttribute{name:"iconScale";value:1.0}

 

    PathLine{x:coverFlow.width;y:coverFlow.height/3;}

    PathAttribute{name:"iconZ";value:0}

    PathAttribute{name:"iconAngle";value:-70}

    PathAttribute{name:"iconScale";value:0.6}

    PathPercent{value:1.0}

}

       这里通过PathAttribute设置了路径上指定位置的特性,分别设置了Z值、角度和缩放,在PathAttribute中设置的特性本身不会起作用,但是可以暴露给视图中的委托使用,例如iconZ可以在委托中使用PathView.iconZ访问到。下面修改委托MyDelegate.qml的内容:

Item{

    id:delegateItem

    width:320

    height:450

    z:PathView.iconZ

    scale:PathView.iconScale

 

    Image{

       id:dlgImg

       source:url

       width:delegateItem.width

       height:delegateItem.height

    }

 

    transform:Rotation{

       origin.x:dlgImg.width/2

       origin.y:dlgImg.height/2

        axis{x:0;y:1;z:0}

       angle:delegateItem.PathView.iconAngle

    }

}

    这里主要是将路径中设置的特性值应用到委托中,这样就可以对模型中每一个条目都起作用。现在重新构建程序(直接运行程序qml文件的修改可能无法生效),然后运行,效果如下图所示:

 

 

    现在已经有些感觉了,但还是比较乱,标准的应该是中间一个图片,两边各两个图片才对啊。要实现这个,需要在PathView的定义最后添加下面两行关键代码:

preferredHighlightBegin:0.5

preferredHighlightEnd:0.5

       重新构建并运行程序,效果如下图所示:

 

 

 

    现在已经基本成型,但是离高大上还是差了点什么。

 

化腐朽为神奇

 

    要实现那炫酷的效果,需要做以下几步。

    第一步,就是把背景设置为纯黑色,这样可以添加神秘感并且可以遮盖掉那些不完美的细节。在CoverFlow.qml文件中PathView定义之前添加如下代码:

Rectangle{

    anchors.fill:parent

    color:"black"

}

       一定要放在PathView定义之前,不然会把PathView也遮掉,如果想放到后面,那么就设置一下z值。现在效果如下图所示:

 

 

    

    第二步,设置投影。将MyDelegate.qml中Image的定义修改如下:

Column  {

    id:delegate

    spacing:10

 

    Image{

       id:dlgImg

       source:url

       width:delegateItem.width

       height:delegateItem.height

    }

 

    Image{

       id:reflection

       width:delegateItem.width

       height:delegateItem.height

       source:dlgImg.source

       opacity:0.4

       transform:Scale{

           yScale:-1

           origin.y:delegateItem.height/2

       }

    }

}

    这里在原图下面又添加了一个翻转的图片,现在的效果如下图所示:

 

 

 

    第三步,使用渐变遮罩投影。现在整个图片的投影全部显示出来了,相互叠加,显得很乱,下面使用半透明的渐变填充来遮罩投影,将前面添加的投影Image部分修改如下:

Item{

    width:delegateItem.width

    height:delegateItem.height

   

    Image{

       id:reflection

       source:dlgImg.source

       transform:Scale{

           yScale:-1

           origin.y:delegateItem.height/2

       }

    }

   

    LinearGradient{

       width:delegateItem.width

       height:delegateItem.height

       gradient:Gradient{

           GradientStop{position:0.0;color:  Qt.rgba(0,0,0,0.1)}

           GradientStop{position:0.4;color:  Qt.rgba(0,0,0,1)}

       }

    }

}

 

    这里将Image放到了一个Item中,然后为Item添加了一个半透明的黑色遮罩,从而实现了显示部分投影然后逐渐消失的效果。要使用Gradient类型,记着添加:

import QtGraphicalEffects 1.0

导入语句。现在运行程序,效果如下图所示:

 

 

 

    第四步,细节优化。为了更加完美,还可以添加缩放动画、增加路径节点数、为图片设置边框等,这些操作这里就不再列出代码了,有需要的朋友可以到论坛下载源码。

 

结语

 

        Qt Quick在实现特效方面是非常强大的,可以说只有想不到的没有做不到的,关键是要灵活使用各种控件和QML类型,说到灵活使用,那就必须基础牢靠,然后多加练习。

 


 

欢迎扫一扫关注我的公众号:

 

讨论该文章或下载附件,请点击这里

 
 

Qt开源社区——开源 共享 自由

QQ群
会员交流群:186601429
书友交流群:190740635
交流总群:优秀会员邀请加入
邮箱
商务合作:yafeilinux@163.com

微信扫一扫
查看精品教程!

 

posted on 2018-03-29 15:03  qushaohui  阅读(1433)  评论(0)    收藏  举报

导航