新浪微博
腾讯微博
会员列表
统计排行
基本信息
到访IP统计
管理团队
管理统计
在线会员
会员排行
版块排行
帖子排行
标签排行
帮助
下拉
用户名
电子邮箱
用户名
密 码
记住登录
登录
找回密码
注册
快捷通道
关闭
您还没有登录,快捷通道只有在登录后才能使用。
立即登录
还没有帐号? 赶紧
注册一个
首页
论坛
Qt下载
作品展
群组
个人中心
捐赠、管理与开发
邮件订阅
帖子
文章
日志
用户
版块
群组
帖子
搜索
QTCN开发网
>
Qt应用版
>
Qml组件化编程3-动态切换皮肤
发帖
回复
返回列表
新帖
3190
阅读
2
回复
Qml组件化编程3-动态切换皮肤
[复制链接]
上一主题
下一主题
离线
dd759378563
UID:176218
注册时间
2016-10-15
最后登录
2019-12-19
在线时间
19小时
发帖
52
搜Ta的帖子
精华
0
金钱
577
威望
64
贡献值
0
好评度
54
访问TA的空间
加好友
用道具
新手上路
关闭
个人中心可以申请新版勋章哦
立即申请
知道了
加关注
发消息
只看楼主
倒序阅读
楼主
发表于: 2019-05-18
简介
本文是《
Qml
组件化编程》系列文章的第三篇,涛哥将教大家,如何在Qml中实现动态换皮肤。顺带会分享一些Qt小技巧。
文章主要发布在
涛哥的博客
和
知乎专栏-涛哥的Qt进阶之路
。
效果预览
效果类似于网易云音乐
顺便说一下,这是涛哥创建的TaoQuick项目,后续的各种组件、效果会全部集中在这个项目里。
文章中涉及的代码,都会先贴出来。整个工程的代码,在积累到一定程度后,会开放在github上。
必要的基础
可能有读者会疑惑,涛哥前两篇文章还在讲如何封装基础组件,这第三篇直接就来换皮肤?是不是跨度有点大?
其实换皮肤是一个很基础的功能,如果要做最好在项目初期就做起来,后期想要做换皮肤会困难一些(工作量大)。
如果你的项目做了很多组件化的封装,再做换皮肤会轻松一些。
QObject自定义属性
Qml中有一个类型叫QtObject,涛哥非常喜欢使用这个类型。
以前在写Qt/C++代码中的自定义QObject时,经常需要写一些自定义的Q_PROPERTY,以及实现set、get函数、change信号
如果纯手工写,挺累人的,涛哥曾写过自动生成器,相信很多人也写过类似的工具。
后来涛哥发现,QtCreator有自动生成的功能,只要写上Q_PROPERTY那一行,再用右键菜单生成即可,
高效率人士也可以使用快捷键,光标放在Q_PROPERTY上,按Alt + Enter。
有时候需要把set函数的参数改成const T &类型来减少内存拷贝,并把函数实现移动到cpp文件中。(这都是
C++
的诟病)
然而,在Qml中,有更加方便的QtObject,
复制代码
Item {
QtObject { //定义一个QtObject,相当于Qt/c++代码中的QObject
id: dataObj
property string name: "Hello" //这就定义了一个string类型的属性name,初始值设为"Hello"
//定义完了,已经自带了onNameChanged信号。name被重新赋值时会触发信号
//给这个信号写一个处理函数,就相当于连接上了槽函数。
onNameChanged: {
console.info("name:", name)
}
}
...
Button {
...
onClicked: { //演示: 按钮按下时,修改前面QtObject的name属性
dataObj.name = "World";
}
}
...
}
(哈哈,工作量和心理负担一下子减轻了很多,头发的数量也能保住了。再也不想回去写Qt/C++的属性了。)
全局单例
涛哥写了一个单独的qml文件,顶层就是一个QtObject类型,里面会有一大堆属性。
颜色、
字体
一类的配置都在这里。
复制代码
// GlobalConfig.qml
import QtQuick 2.0
QtObject {
property color titleBackground: "#c62f2f" //标题栏的背景色
property color background: "#f6f6f6" //标题栏之外的部分的背景色
property color reserverColor: "#ffffff" //与背景色相反的对比色
property color textColor: "black" //文本颜色
}
然后在main.qml中实例化它
复制代码
// main.qml
Item {
width: 800
height: 600
GlobalConfig {
id: gConfig
}
...
}
Qml有个特性,子页面实例可以通过id访问父页面中的实例,读 写其属性、调用其函数。
在main.qml中实例化的对象,相当于是全局的了,它的id是可以在所有main.qml的子页面中访问到的。
(当然还有一种方式,通过qmldir指定单例,这种留着后面再说)
实现
皮肤的配置和原理
下面是TaoQuick中使用的gConfig
复制代码
// GlobalConfig.qml
QtObject {
property color titleBackground: "#c62f2f"
property color background: "#f6f6f6"
property color reserverColor: "#ffffff"
property color textColor: "black"
property color splitColor: "gray"
property int currentTheme: 0
onCurrentThemeChanged: {
var t = themes.get(currentTheme)
titleBackground = t.titleBackground
background = t.background
textColor = t.textColor
}
readonly property ListModel themes: ListModel {
ListElement {
name: qsTr("一品红")
titleBackground: "#c62f2f"
background: "#f6f6f6"
textColor: "#5c5c5c"
}
ListElement {
name: qsTr("高冷黑")
titleBackground: "#191b1f"
background: "#222225"
textColor: "#adafb2"
}
ListElement {
name: qsTr("淑女粉")
titleBackground: "#faa0c5"
background: "#f6f6f6"
textColor: "#5c5c5c"
}
ListElement {
name: qsTr("富贵金")
titleBackground: "#fed98f"
background: "#f6f6f6"
textColor: "#5c5c5c"
}
ListElement {
name: qsTr(" 清爽绿")
titleBackground: "#58c979"
background: "#f6f6f6"
textColor: "#5c5c5c"
}
ListElement {
name: qsTr("苍穹蓝")
titleBackground: "#67c1fd"
background: "#f6f6f6"
textColor: "#5c5c5c"
}
}
}
涛哥在所有的Page页面中,相关颜色设置都绑定到gConfig的相应属性上。
那么换皮肤,只需要修改gConfig中的颜色相关属性即可。因为修改属性时会触发change信号,而所有的Page都绑定了
gConfig的属性,会自动在发生change时重新读属性,修改后的颜色自动就生效了。
这里顺带说一下,主题的颜色相关属性越少越好,因为太多了不容易识别、不好维护,
文章1
Qml组件化编程1-按钮的定制与封装
中提到的Qt.lighter和Qt.darker就是一种减少颜色属性数量的神器。
皮肤选择器
再来看一下,涛哥参考 网易云音乐 做的皮肤选择器
复制代码
TImageBtn { //图片按钮,参考文章1
width: 20
height: 20
anchors.verticalCenter: parent.verticalCenter
imageUrl: containsMouse ? "qrc:/Image/Window/skin_white.png" : "qrc:/Image/Window/skin_gray.png"
onClicked: {
skinBox.show()
}
TPopup { //自定义的弹窗,带三角尖尖的那个。
id: skinBox
barColor: gConfig.reserverColor
backgroundWidth: 280
backgroundHeight: 180
contentItem: GridView {
anchors.fill: parent
anchors.margins: 10
model: gConfig.themes
cellWidth: 80
cellHeight: 80
delegate: Item {
width: 80
height: 80
Rectangle { //表示主题色的色块
anchors.fill: parent
anchors.margins: 4
height: width
color: model.titleBackground
}
Rectangle { //主题色边框,鼠标悬浮时显示
anchors.fill: parent
color: "transparent"
border.color: model.titleBackground
border.width: 2
visible: a.containsMouse
}
Text { //主题名字
anchors {
left: parent.left
bottom: parent.bottom
leftMargin: 8
bottomMargin: 8
}
color: "white"
text: model.name
}
Rectangle { //右下角圆圈圈,当前选中的主题
x: parent.width - width
y: parent.height - height
width: 20
height: width
radius: width / 2
color: model.titleBackground
border.width: 3
border.color: gConfig.reserverColor
visible: gConfig.currentTheme === index
}
MouseArea { //鼠标状态
id: a
anchors.fill: parent
hoverEnabled: true
onClicked: { //切主题操作
gConfig.currentTheme = index
}
}
}
}
}
}
带三角形尖尖的弹窗组件
复制代码
// TPopup.qml
import QtQuick 2.9
import QtQuick.Controls 2.5
Item {
id: root
anchors.fill: parent
property alias popupVisible: popup.visible
property alias contentItem: popup.contentItem
property color barColor: "white"
property alias backgroundItem: background
property real backgroundWidth: 200
property real backgroundHeight: 160
property color borderColor: barColor
property real borderWidth: 0
property real verticalOffset: 20
//矩形旋转45度,一半被toolTip遮住(重合),另一半三角形和ToolTip组成一个带箭头的ToolTip
Rectangle {
id: bar
visible: popup.visible
rotation: 45
width: 16
height: 16
color: barColor
//水平居中
anchors.horizontalCenter: parent.horizontalCenter
//垂直方向上,由ToolTip的y值,决定位置
anchors.verticalCenter: parent.bottom
anchors.verticalCenterOffset: verticalOffset
}
Popup {
id: popup
width: backgroundWidth
height: backgroundHeight
background: Rectangle {
id: background
color: barColor
radius: 8
border.color:borderColor
border.width: borderWidth
}
}
function show() {
popup.x = (root.width - popup.width) / 2
popup.y = root.height + verticalOffset
popupVisible = true
}
function hide() {
popupVisible = false
}
}
转载声明
文章出自涛哥的博客 – 点击这里查看涛哥的博客
文章采用
知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议
进行许可, 转载请注明出处, 谢谢合作 ©
涛哥
联系方式
作者
涛哥
开发
理念
弘扬鲁班文化,传承工匠精神
博客
https://jaredtao.github.io
知乎
https://www.zhihu.com/people/wentao-jia
邮箱
jared2020@163.com
微信
xsd2410421
QQ
759378563
请放心联系我,乐于提供咨询服务,也可洽谈商务合作相关事宜。
共
条评分
涛哥是个Qml高手,著有《Qml组件化编程》《Qml特效》系列教程,见知乎专栏-Qt进阶之路:https://zhuanlan.zhihu.com/TaoQt
或微信公众号:Qt进阶之路
回复
举报
分享到
淘江湖
新浪
QQ微博
QQ空间
开心
人人
豆瓣
网易微博
百度
鲜果
白社会
飞信
离线
dd759378563
UID:176218
注册时间
2016-10-15
最后登录
2019-12-19
在线时间
19小时
发帖
52
搜Ta的帖子
精华
0
金钱
577
威望
64
贡献值
0
好评度
54
访问TA的空间
加好友
用道具
新手上路
加关注
发消息
只看该作者
1楼
发表于: 2019-05-18
代码格式已经修正
共
条评分
涛哥是个Qml高手,著有《Qml组件化编程》《Qml特效》系列教程,见知乎专栏-Qt进阶之路:https://zhuanlan.zhihu.com/TaoQt
或微信公众号:Qt进阶之路
回复
举报
离线
big_mouse
UID:144959
注册时间
2013-07-28
最后登录
2020-04-24
在线时间
467小时
发帖
186
搜Ta的帖子
精华
0
金钱
5340
威望
197
贡献值
0
好评度
187
访问TA的空间
加好友
用道具
禁止发言
加关注
发消息
只看该作者
2楼
发表于: 2020-04-15
共
条评分
回复
举报
发帖
回复
返回列表
http://www.qtcn.org/bbs
访问内容超出本站范围,不能确定是否安全
继续访问
取消访问
快速回复
限100 字节
您目前还是游客,请
登录
或
注册
进入高级模式
文字颜色
发 布
回复后跳转到最后一页
上一个
下一个
关闭
补充发布信息
验证码:
发 布
隐藏
快速跳转
站务及资讯
网站公告
新闻资讯
Qt官方发布
网站管理
Qt应用及资源
Qt 作品展
Qt代码秀
Qt应用版
Qt技术讨论区
Qt安装与发布
Qt中文处理
Qt基础编程
Qt QML开发
Qt嵌入式开发
Qt移动平台开发
其它技术开发讨论区
Qt图书专区
《C++ GUI Qt 4编程》(第2版)专栏
《Qt高级编程》专栏
《零基础学Qt4编程》专栏
《Qt设计模式》(第2版) 图书专栏
Python Qt GUI快速编程
Qt项目开发区
天池项目
Qt开放平台开发库
机械CAD
扇贝词典
非活跃项目区
社区中心
帖子回收站(Trash)
招聘、求职、供求、广告等
休闲娱乐
关闭
关闭
选中
1
篇
全选