找回密码
 立即注册

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

发表于 2017-2-6 01:19:31 | 显示全部楼层 |阅读模式
导语

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


开发环境

Win 7 + Qt 5.8.0

实现功能

    如果大家了解过QMLQt 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.qmlImage的定义修改如下:
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类型,说到灵活使用,那就必须基础牢靠,然后多加练习。



欢迎长按下图→识别图中二维码或者扫一扫关注我的公众号:


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x

评分

参与人数 2人气 +3 收起 理由
暖心羊 + 1
FantasyDJC + 2 对我帮助很大!

查看全部评分

回复

使用道具 举报

发表于 2017-2-6 15:23:57 | 显示全部楼层
微信下面如果可以留言就好了。。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-2-6 19:42:29 | 显示全部楼层
linux-qt 发表于 2017-2-6 15:23
微信下面如果可以留言就好了。。

公众号需要创建一段时间,有一定的原创文章之后才能开通留言。
回复 支持 反对

使用道具 举报

发表于 2017-2-10 10:38:08 | 显示全部楼层
亚飞老师,为什么我运行出来的结果倒影的渐变是反的呢?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-2-10 21:11:59 | 显示全部楼层
fifthsun 发表于 2017-2-10 10:38
亚飞老师,为什么我运行出来的结果倒影的渐变是反的呢?

不会把,你发个截图看看!
回复 支持 反对

使用道具 举报

发表于 2017-2-21 14:05:20 | 显示全部楼层
亚飞老师,我现在存在一个状况
CoverFlow{
       anchors.fill:parent
       model:model
   }
我新建一个工程,写到这步的时候,CoverFlow 这个没有提示,强打的话报错。qt5.8.0
但是我同时再打开你的程序后(我新建的程序和你的mycoverflow.pro同时打开的情况下),CoverFlow这个就有提示了。
我如果关闭您的程序,然后我的程序CoverFlow又报错了。
回复 支持 反对

使用道具 举报

发表于 2017-2-21 14:24:36 | 显示全部楼层
本帖最后由 FantasyDJC 于 2017-2-21 14:29 编辑

老师 我错了。
CoverFlow类还没有建。。报错是正常的。。没注意下面新建CoverFlow类了。
我错了,只见树木不见森林
回复 支持 反对

使用道具 举报

发表于 2017-3-22 14:02:46 | 显示全部楼层
老师,你最后的第三步里,在投影中修改Image部分的代码有点问题,应该在Image{}里边再加上三句:width:delegateItem.width;height:delegateItem.height;opacity: 0.4;
回复 支持 反对

使用道具 举报

发表于 2017-6-12 18:54:52 | 显示全部楼层
Qter豆不够,哇哇哇,好像学习这个啊。。。。。
回复 支持 反对

使用道具 举报

发表于 2017-6-13 16:30:10 | 显示全部楼层
好像学习这个啊。。。。。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

12下一页

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

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