创建可以重复利用的QML Component--Podcast播放器代码实例
来源:互联网 发布:贴吧营销软件 编辑:程序博客网 时间:2024/04/29 17:15
在我们设计QML应用时,很重要的一点就是设计一个可以被重复利用的软件Component.它可以反复在其它的应用中被利用.这如同在我们的C++及其它语言中设计自己的应用一样,我们可以创建自己的模块.只需要修改很少的部分或甚至不用做任何的修改就可以被其它的应用广泛使用.我们在前两天的文章"利用Ubuntu Component Store来增加我们的QML Components"中已经做过一些介绍了.今天我们通过一个具体的实例来展示是如何做的.在今天的例程中,我们来介绍一个podcast播放器的实例.
在我们今天设计的应用中,有两个页面.第一个页面,是一个podcast RSS feed的介绍及其播放audio的列表.在第二个页面中,显示的是它的一个logo的图像及几个可以用于播放的按钮.
这个设计采用了一个叫做GenericPodcastApp.qml的Component.其设计如下:
GenericPodcastApp.qml
import QtQuick 2.0import Ubuntu.Components 0.1import QtQuick.XmlListModel 2.0import Ubuntu.Components.ListItems 0.1 as ListItemimport QtMultimedia 5.0PageStack { id: ps Component.onCompleted: ps.push(front) property alias squareLogo: logo.source property alias author: author.text property alias category: category.text property alias name: front.title property alias description: desc.text property alias feed: rssmodel.source Action { id: reloadAction text: "Reload" iconName: "reload" onTriggered: rssmodel.reload() } Page { id: front visible: true tools: ToolbarItems { ToolbarButton { action: reloadAction } } Flickable { anchors.fill: parent contentHeight: row.height + desc.height + showlist.height + desc.anchors.topMargin + showlist.anchors.topMargin Row { id: row width: parent.width anchors.top: parent.top anchors.left: parent.left anchors.topMargin: units.gu(1) anchors.leftMargin: units.gu(1) anchors.rightMargin: units.gu(1) spacing: units.gu(2) UbuntuShape { id: logoshape width: parent.width / 3 height: parent.width / 3 image: Image { id: logo fillMode: Image.PreserveAspectFit } ActivityIndicator { running: logo.status != Image.Ready anchors.centerIn: logoshape } } Column { width: row.width - row.spacing - row.anchors.leftMargin- row.anchors.rightMargin - logoshape.width spacing: units.gu(1) anchors.bottom: parent.bottom Label { id: author fontSize: "small" wrapMode: Text.WordWrap width: parent.width } Label { id: category wrapMode: Text.WordWrap width: parent.width fontSize: "small" } } } Label { id: desc anchors.top: row.bottom anchors.left: parent.left anchors.topMargin: units.gu(2) anchors.leftMargin: row.anchors.leftMargin width: parent.width - (row.anchors.leftMargin * 2) wrapMode: Text.WrapAtWordBoundaryOrAnywhere property bool expanded: false clip: true height: { if (desc.contentHeight > units.gu(12) && !expanded) { return units.gu(12) } return desc.contentHeight } Rectangle { color: "black" width: moretxt.contentWidth + units.gu(2) height: moretxt.contentHeight anchors.bottom: desc.bottom anchors.right: desc.right Label { id: moretxt color: "white" anchors.centerIn: parent text: desc.expanded ? "<<" : ">>" } visible: desc.contentHeight > units.gu(12) } MouseArea { anchors.fill: parent onClicked: desc.expanded = !desc.expanded } } Column { id: showlist anchors.top: desc.bottom anchors.topMargin: units.gu(2) width: parent.width Repeater { model: rssmodel ListItem.Standard { text: title width: parent.width progression: true onClicked: { ps.push(episode, {download: model.download, summary: model.summary, title: model.title}); } } } } ActivityIndicator { anchors.top: desc.bottom anchors.topMargin: units.gu(2) height: reloadbutton.height width: height anchors.horizontalCenter: parent.horizontalCenter running: rssmodel.status != XmlListModel.Ready && rssmodel.status != XmlListModel.Error } } } Page { id: episode property string download property string summary visible: false Flickable { anchors.fill: parent contentHeight: biglogo.height + positionbar.height + buttons.height + epdesc.height + (epcol.spacing * 4) Column { id: epcol width: parent.width spacing: units.gu(2) Image { id: biglogo source: logo.source width: parent.width height: parent.width fillMode: Image.PreserveAspectFit } Rectangle { id: positionbar width: buttons.width anchors.horizontalCenter: parent.horizontalCenter height: units.gu(5) color: "transparent" Rectangle { id: actualbar width: parent.width height: units.gu(0.5) color: "#999999" anchors.verticalCenter: parent.verticalCenter anchors.centerIn: parent } Rectangle { width: units.gu(0.5) height: units.gu(2) color: "#444444" anchors.verticalCenter: actualbar.verticalCenter x: actualbar.width * aud.position / aud.duration } MouseArea { anchors.fill: parent onPressed: { aud.seek(aud.duration * mouse.x / actualbar.width) } } } Row { id: buttons spacing: units.gu(2) anchors.horizontalCenter: parent.horizontalCenter Button { text: "<<30" onClicked: aud.seek(aud.position - 30000) } Button { text: aud.status == Audio.Loading ? "load" : (aud.playbackState == Audio.PlayingState ? "Stop" : "Play") onClicked: { aud.source = episode.download; if (aud.playbackState == Audio.PlayingState) { aud.pause(); } else { aud.play(); } console.log(aud.duration, aud.position); } } Button { text: "30>>" onClicked: aud.seek(aud.position + 30000) } } Label { id: epdesc width: parent.width - units.gu(4) anchors.horizontalCenter: parent.horizontalCenter text: episode.summary wrapMode: Text.Wrap color: "white" textFormat: Text.RichText } } } } XmlListModel { id: rssmodel query: "/rss/channel/item" namespaceDeclarations: "declare namespace itunes='http://www.itunes.com/dtds/podcast-1.0.dtd'; declare namespace content='http://purl.org/rss/1.0/modules/content/';" XmlRole { name: "title"; query: "title/string()" } XmlRole { name: "pubDate"; query: "pubDate/string()" } XmlRole { name: "download"; query: "enclosure/@url/string()" } XmlRole { name: "summary"; query: "content:encoded/string()" } } Audio { id: aud }}
在上面的设计中非常简单.我们通过在Component中设计一些property,在使用这个Component时只需要在外面对他们进行赋值即可.就像我以前在有些教程中讲到的.如果我们需要修改到这个Component中的其中的子Component的属性的话,我们可以通过QML中的alias来实现.第一个页面的最上面显示的是一个podcast的最基本的信息.在它的最下面,它使用了一个repeater来显示所有的epsode列表.
Column { id: showlist anchors.top: desc.bottom anchors.topMargin: units.gu(2) width: parent.width Repeater { model: rssmodel ListItem.Standard { text: title width: parent.width progression: true onClicked: { ps.push(episode, {download: model.download, summary: model.summary, title: model.title}); } } } }
在这里我们使用了rssmodel,它的定义如下:
XmlListModel { id: rssmodel query: "/rss/channel/item" namespaceDeclarations: "declare namespace itunes='http://www.itunes.com/dtds/podcast-1.0.dtd'; declare namespace content='http://purl.org/rss/1.0/modules/content/';" XmlRole { name: "title"; query: "title/string()" } XmlRole { name: "pubDate"; query: "pubDate/string()" } XmlRole { name: "download"; query: "enclosure/@url/string()" } XmlRole { name: "summary"; query: "content:encoded/string()" } }
更多关于XmlListModel的使用,可以参阅API介绍.在我的博客中也有很多的介绍.大家可以参阅我的一些设计的例程.
到目前为止,我们已经设计好我的GenericPodcastApp Component.如果在其它的地方需要应用它的话,我们只需要这么做:
Main.qml
import QtQuick 2.0import Ubuntu.Components 1.1/*! \brief MainView with a Label and Button elements.*/MainView { // objectName for functional testing purposes (autopilot-qt5) objectName: "mainView" // Note! applicationName needs to match the "name" field of the click manifest applicationName: "podcast.liu-xiao-guo" /* This property enables the application to change orientation when the device is rotated. The default is false. */ //automaticOrientation: true // Removes the old toolbar and enables new features of the new header. useDeprecatedToolbar: false width: units.gu(60) height: units.gu(85) GenericPodcastApp { name: "Bad Voltage" squareLogo: "images/logo.jpg" author: "Stuart Langridge, Jono Bacon, Jeremy Garcia, and Bryan Lunduke" category: "Technology" feed: "http://www.badvoltage.org/feed/ogg/" description: "Every two weeks Bad Voltage delivers an amusing take on technology, Open Source, politics, music, and anything else we think is interesting." }}
它的应用非常地简单.我们只需要对它里面的properties进行赋值即可.我们很容地把它修个成为其它的源的podcast.当然我们也可以利用这个设计更加复杂的应用,这样,我们可以把我们想要的rss feed轻易地加入到我们的podcast列表中.这个练习就交给我们的开发者吧.
整个项目的源码在:https://github.com/liu-xiao-guo/podcast
- 创建可以重复利用的QML Component--Podcast播放器代码实例
- 利用Ubuntu Component Store来增加我们的QML Components
- QML 中神秘的 Component
- Component 抽象和重复利用
- 基于QML的播放器实现
- Android中利用反射机制创建实例的代码
- QML: component
- qml LAVFSplitter播放器
- 在QML中运用Component.incubateObject()来实现对创建object的lifecyle进行监控
- QT可以播放gif的实例
- 利用Android 自定义的悬浮播放器实例
- android 音乐文件重复播放的代码
- QT关于qml的Component事件
- 网页中可以播放视频的代码
- 【经典实例】利用C#反射动态编译代码,创建类的实例,并调用其成员
- 常用网页中嵌套播放器的代码实例
- QML之Repeater重复器
- iOS 利用AVPlayer创建视频播放器
- Android中获取屏幕物理尺寸的方法
- 架构之路(二):性能
- android-----ListView和GridView的用法
- css圆形图片处理示例(方形图片变圆形图片)
- Error:Cause: org/gradle/api/publication/maven/internal/DefaultMavenFactory Android
- 创建可以重复利用的QML Component--Podcast播放器代码实例
- OutputStreamWriter和BufferedWriter疑惑
- 探索九月
- ACM相关
- smarty中,如果改变模板,刷新页面没有变化,该如何解决?
- Oracle SQL优化总结
- 浏览文本文件
- RabbitMQ安装
- jquery 实现 div 拖动效果