当前位置: 首页 > news >正文

Qt+qss动态属性改变控件状态切换的样式

先说点基础的吧,qt的样式实现,常见的主要有三种方式,分别为:
1.ui界面中右键样式表直接添加
2.代码中对控件设置样式setStyleSheet
3.外部预设好qss文件,代码中加载后设置样式
实际工作开发中,我推荐使用优先级为3>2>1,理由如下:
在ui界面中直接添加样式,优点是可以实时看到基本的ui效果,但对于某些需要切换状态的ui,会比较麻烦。例如我预设了一个标签“没信号”的效果,当我的设备有信号时,我需要在代码中进行“有信号”效果的设置,这样一来,我们难免会在代码中进行重复的setStyleSheet,1和2搭配起来可以正常使用,只是难以管理我们的样式。
另外插一嘴,如果我们在ui界面中设置好了控件的布局,那后续我们在代码中想要改变布局,是极其麻烦的,比如我有四个按钮,原本是上下左右排列的,结果来了一个甲方需求,需要变成从左到右的排列。这样一来,我只能在ui界面中拖拽按钮进行布局,来满足甲方的需求。要命的来了,甲方突然又说,我需要两个版本,上下左右和从左到右都要。你就很头疼了,每次编译发布的时候都需要去修改ui界面,麻烦至极,你甚至一气之下想要拷贝多份代码……这种思路显然是不对的。遇到这种情况,我们应该通过代码来灵活布局,由代码中创建好四个控件,然后新建布局类进行布局。同样,这里的控件样式也只能由代码来进行设置。
然而,我们一旦在多处代码中使用了setStyleSheet,就会让我们的样式设置变得凌乱,特别对于状态切换,比如一个按钮点击了之后,需要切换成其他状态,这部分样式设置一般放在信号槽当中。针对这种情况,我们期望对所有样式表进行有效的管理,于是qss文件这种方式就应运而生了。
简单来说,就是将所有样式表放进qss文件中,通过文件读取来进行统一设置(具体实现就不赘述了。)
然而到了这里,还没有解释控件状态切换需要怎么做。别急,现在就来。

Qt+qss动态属性改变控件状态切换的样式
一个QPushbutton按钮,一般来说会存在三态(常态、鼠标悬浮、鼠标点击按下),复杂的还会有选中和取消使能的状态。这种情况,我们的样式表会这样写:

QPushButton#btn_xxx{
border-image: url(:/image/xxx.png);
color: #000000;
font-size: 18px;
font-family: 黑体;
min-width:110;
max-width:110px;
min-height:40px;
max-height:40px;
}
QPushButton#btn_xxx:hover{
border-image: url(:/image/xxx_over.png);
}
QPushButton#btn_xxx:pressed{
color: #ffffff;
border-image: url(:/image/xxx_down.png);
}
QPushButton#btn_xxx:checked{
color: #ffffff;
border-image: url(:/image/xxx_checked.png);
}
QPushButton#btn_xxx:disabled{
color: #ffffff;
border-image: url(:/image/xxx_disabled.png);
}

以QPushButton#btn_xxx:pressed为例,分别为类名,对象名和控件状态,btn_xxx是这个按钮(这类按钮)的名称,记得要setObjectName,样式表才会生效哦。而pressed是QPushButton自带的一种控件状态,其他控件可不一定有。
然而,这一套样式表只针对于按钮的一种“状态”,这里的状态指的是不同的样式,比如绿色的按钮和红色的按钮,两种颜色的按钮分别都有以上的五种控件状态。
如何进行不同颜色样式的状态切换呢?我们需要添加控件的属性setProperty
首先,样式表的QPushButton#btn_xxx:pressed要进行改造,变为QPushButton#btn_xxx:pressed[State=‘Green’],这样该条样式就具有了属性,即当该控件的属性State为Green时,才会应用这条样式。
于是我们的样式表可以改成:

//green
QPushButton#btn_xxx[State='Green']{
border-image: url(:/image/xxx.png);
color: #000000;
font-size: 18px;
font-family: 黑体;
min-width:110;
max-width:110px;
min-height:40px;
max-height:40px;
}
QPushButton#btn_xxx:hover[State='Green']{
border-image: url(:/image/xxx_over.png);
}
QPushButton#btn_xxx:pressed[State='Green']{
color: #ffffff;
border-image: url(:/image/xxx_down.png);
}
QPushButton#btn_xxx:checked[State='Green']{
color: #ffffff;
border-image: url(:/image/xxx_checked.png);
}
QPushButton#btn_xxx:disabled[State='Green']{
color: #ffffff;
border-image: url(:/image/xxx_disabled.png);
}//red
QPushButton#btn_xxx[State='Red']{
border-image: url(:/image/xxx.png);
color: #000000;
font-size: 18px;
font-family: 黑体;
min-width:110;
max-width:110px;
min-height:40px;
max-height:40px;
}
QPushButton#btn_xxx:hover[State='Red']{
border-image: url(:/image/xxx_over.png);
}
QPushButton#btn_xxx:pressed[State='Red']{
color: #ffffff;
border-image: url(:/image/xxx_down.png);
}
QPushButton#btn_xxx:checked[State='Red']{
color: #ffffff;
border-image: url(:/image/xxx_checked.png);
}
QPushButton#btn_xxx:disabled[State='Red']{
color: #ffffff;
border-image: url(:/image/xxx_disabled.png);
}

哎,没错,样式表的代码量确实多了一倍,但如此一来,我们就能通过代码来切换状态啦,记得setProperty之后要调用unpolish和polish,不然样式可能无法成功修改

void xxx::slot_xxx(bool b_flag)
{if(b_flag){btn_xxx->setProperty("State","Green");btn_xxx->style()->unpolish(btn_video_lock); //清除旧的样式btn_xxx->style()->polish(btn_video_lock);   //更新为新的样式}else{btn_xxx->setProperty("State","Red");btn_xxx->style()->unpolish(btn_video_lock); //清除旧的样式btn_xxx->style()->polish(btn_video_lock);   //更新为新的样式}
}

到了这里,我们基本上就可以用qss一种方式,来实现我所需要的全部需求了。
另外,如果甲方需要整体更换ui,类似换肤这种需求的话,我们直接拷贝一份qss进行修改,由代码来加载不同的qss文件即可。

相关文章:

  • Flutter打包网络问题解决办法
  • 【Go语言精进之路】构建高效Go程序:了解切片实现原理并高效使用
  • 《编译原理》期末考试复习手写笔记(二)+真题(第四、五、六章)+课后习题答案
  • Flutter中同步与异步
  • 10倍速开发开关电源:PSIM DLL集成指南与如何单步调试你的代码
  • 【面试干货】如何选择MySQL数据库存储引擎(MyISAM 或 InnoDB)
  • 使用 Python 的 Tkinter 来创建 GUI 应用程序
  • 【排序算法】总结篇
  • Linux-常用命令-常用设置
  • 测试testing06081
  • 华为端云一体化开发 初始化云db表结构和表数据(实践2.0)(HarmonyOS学习第七课)
  • Electron qt开发教程
  • python代码中参数的默认值
  • 前端开发高频面试题
  • C++三大特性之多态
  • 【402天】跃迁之路——程序员高效学习方法论探索系列(实验阶段159-2018.03.14)...
  • 【附node操作实例】redis简明入门系列—字符串类型
  • Create React App 使用
  • Cumulo 的 ClojureScript 模块已经成型
  • IDEA常用插件整理
  • IP路由与转发
  • JavaScript设计模式与开发实践系列之策略模式
  • Java多线程(4):使用线程池执行定时任务
  • SpringBoot几种定时任务的实现方式
  • 第13期 DApp 榜单 :来,吃我这波安利
  • 蓝海存储开关机注意事项总结
  • 前端_面试
  • 微信公众号开发小记——5.python微信红包
  • 协程
  • 再次简单明了总结flex布局,一看就懂...
  • 怎么把视频里的音乐提取出来
  • 阿里云ACE认证学习知识点梳理
  • 如何正确理解,内页权重高于首页?
  • ​​​​​​​​​​​​​​汽车网络信息安全分析方法论
  • ​【经验分享】微机原理、指令判断、判断指令是否正确判断指令是否正确​
  • ​LeetCode解法汇总2670. 找出不同元素数目差数组
  • ​linux启动进程的方式
  • "无招胜有招"nbsp;史上最全的互…
  • #、%和$符号在OGNL表达式中经常出现
  • #gStore-weekly | gStore最新版本1.0之三角形计数函数的使用
  • #vue3 实现前端下载excel文件模板功能
  • #经典论文 异质山坡的物理模型 2 有效导水率
  • #我与Java虚拟机的故事#连载07:我放弃了对JVM的进一步学习
  • ${factoryList }后面有空格不影响
  • %3cli%3e连接html页面,html+canvas实现屏幕截取
  • (1/2)敏捷实践指南 Agile Practice Guide ([美] Project Management institute 著)
  • (145)光线追踪距离场柔和阴影
  • (LeetCode) T14. Longest Common Prefix
  • (待修改)PyG安装步骤
  • (力扣)循环队列的实现与详解(C语言)
  • (三)Kafka离线安装 - ZooKeeper开机自启
  • (转)树状数组
  • .gitignore不生效的解决方案
  • .NET Core IdentityServer4实战-开篇介绍与规划
  • .NET Core实战项目之CMS 第十二章 开发篇-Dapper封装CURD及仓储代码生成器实现