16-2_Qt 5.9 C++开发指南_使用样式表Qss自定义界面

进行本篇介绍学习前,请先参考链接01_1_Qt工程实践_Qt样式表Qss,后再结合本篇进行融合学习如何使用样式表定义界面。

文章目录

  • 1. Qt样式表
  • 2. Qt样式表句法
    • 2.1 一般句法格式
    • 2.2 选择器 (selector)
    • 2.3 子控件(sub-controls)
    • 2.4 伪状态(pseudo-states)
    • 2.5 属性
  • 3. 样式表的使用
    • 3.1 程序中使用样式表
    • 3.2 样式定义的明确性
    • 3.3 样式定义的级联性

1. Qt样式表

Qt 样式表 (style sheet)是用于定制用户界面的强有力的机制,其概念、术语是受到HTML 中的级联样式表(Cascading Style Sheets,CSS)启发而来的,只是 Qt 样式表是应用于窗体界面的。

与 HTML 的 CSS 类似,Qt的样式表是纯文本的格式定义,在应用程序运行时可以载入和解析这些样式定义。使用样式表可以定义各种界面组件(QWidget 类及其子类)的样式,从而使应用程序的界面呈现不同的效果。很多软件具有换肤功能,使用 Qt 的样式表就可以容易地实现这样的功能。
在 UI设计器中集成了 Qt 样式表的编辑功能。在设计窗时,选择窗体或某个界面组件,单击鼠标右键,在弹出的快捷菜单中选择“Change styleSheet”菜单项就可以出现样式表编辑对话框。

2. Qt样式表句法

2.1 一般句法格式

Qt样式表的句法 (syntax)与HTML的CSS 法几乎完全同。Qt 样式表包含一系列的样式法则,一个样式法则由一个选择器(selector)和一些声明(declaration)组成。例如:

QPlainTextEdit{
    font: 12pt“仿宋";
    color: rgb(2552550);
    background-color: rgb(000)
}

其中,QPlainTextEdit就是选择器,表明后面花括号里的样式声明应用于QPlainTextEdit类及其子类。样式声明部分是样式法则列表,每个样式法则由属性和值(key-value)组成,每条法则用分号结束。每条样式法则由“属性:值”构成,例如:

font: 12pt“仿宋";

表示 font 属性,字体大小为 12pt,字体名称为“仿宋”;当一个属性有多个值时,多个值用空格隔开。

2.2 选择器 (selector)

Qt样式表支持 CSS2 中定义的所有选择器,表 16-1显示的是一些常用的选择器。
在这里插入图片描述
这些选择器的定义为选择界面组件提供了灵活性。选择器可以组合使用,一个样式声明可以应用于多个选择器,例如:

QPlainTextEdit,QLineEdit,QPushButton,QCheckBox{
    color: rgb(2552550);
    background-color: rgb(000);
}

这个样式声明将同时应用于 QPlainTextEdit、QLineEdit、QPushButton和QCheckBox 的实例。

QLineEdit[readOnly-"true"], QCheckBox[checked-"true"]
{ background-color: rgb(255,0,0) }

上面的这个样式应用于readOnly 属性为true 的QLineEdit和checked 属性为true的QCheckBox实例,功能是使其背景颜色为红色。
在Qt中,可以为一个界面组件使用QObject::setProperty()设置一个动态属性,例如,在数据表编辑界面上,一些字段是必填字段,就可以为这些字段的关联组件设置一个required 属性为 true,如:

editName-> setProperty("required""true");
comboSex-> setProperty("required”,"true");
checkAgree-> setProperty("reauired","true");

这样设置了三个界面组件的动态属性 required 为 true。

那么,可以应用下面的样式将这种必填字段的背景颜色设置为亮绿色

*[required="true"] {background-color: lime)

2.3 子控件(sub-controls)

对于一些组合的界面组件,需要对其子控件进行选择,如 QComboBox 的下拉按钮,或QSpinBox 的上、下按钮。通过选择器的子控件可以对这些界面元素进行显示效果控制。例如:

QComboBox::drop-down{ image: url(:/images/images/down.bmp);}

选择器QComboBox:drop-down 选择了 QCombBox 的drop-down 子控件,定义的样式是设置其image 属性为资源文件中的图片 down.bmp。

QSpinBox::up-button{ image: url(:/images/images/up.bmp);}
QSpinBox::down-button{ image: url(:/images/images/down.bmp);

这两条样式定义语句分别定义了 QSpinBox 的上、下按钮的图片,用资源文件中的图片替代了缺省的图片。

Qt 中常用的子控件见表 16-2,所有子控件的详细描述见 Qt 的帮助文档
在这里插入图片描述
在这里插入图片描述

2.4 伪状态(pseudo-states)

选择器可以包含伪状态,使得样式法则只能应用于界面组件的某个状态,也就是一种条件应用法则。伪状态出现在选择器的后面,用一个分号 ":"隔开。如下面的样式法则:

QLineEdit:hover{
    background-color: black;
    color: yellow;
}

定义了当鼠标移动到 QLineEdit 上方时 (hover),改变 QLineEdit 的背景色和前景色。

可以对伪状态取反,方法是在伪状态前面加一个感叹号 (!),如:

QLineEdit:!read-only{ background-color: rgb(235,255,251);}

这定义了 readonly 属性为 false 的QLineEdit 的背景色。

伪状态可以串联使用,相当于逻辑与的计算,例如:

QCheckBox:hover:checked{ color: red; }

这定义了当鼠标移动到一个被勾选了的 QCheckBox 组件上方时,其字体颜色变为红色。

伪状态可以并联使用,相当于逻辑或的计算,例如:

QCheckBox:hover,QCheckBox:checked{ color: red; }

这表示鼠标移动到QCheckBox 组件上方,或QCheckBox 组件被勾选时,字体颜色变为红色。

子控件也可以使用伪状态,如:

QCheckBox::indicator:checked{ image: url(:/images/images/checked.bmp);}
QCheckBox::indicator:unchecked{image: url(:/images/images/unchecked.bmp);}

这里定义了 QCheckBox 的 indicator 在 checked 和unchecked 两种状态下的显示图片。

Qt 样式定义中常见的一些伪状态见表 16-3,熟悉这些伪状态并灵活应用可以定义自己想要的界面效果。

在这里插入图片描述
在这里插入图片描述

2.5 属性

Qt样式表内对每一个选择器可定义多条样式规则,每个规则是一个“属性:值”对,Qt 样式表中可定义的属性很多,可以在Qt 的帮助文件中查找“Qt Style Sheets Reference”查看所有属性的详细说明。

使用样式表可以定义组件复杂的显示效果。每个界面组件都可以用如图 16-7 所示的盒子模型(BoxModel)来表示,模型由四个同心矩形表示。
在这里插入图片描述

(1) content 是显示内容矩形区域,如 QLineEdit 用于显示文字的区域,min-width、max-width、min-height 和 max-height 属性定义最大/最小宽度或高度,就是定义这个矩形区,例如:

QLineEdit{
min-width:50px;
max-height:40px;
 }

这定义QLineEdit 最小宽度为 50px,最大高度是 40px,其中 px 是单位,表示像素。

(2) padding 是包围 content 的矩形区域,通过 padding 属性可以定义 padding 的宽度,或padding-top、padding-bottom、padding-left 和 padding-right 分别定义 padding 的上、下、左、右宽度,例如:

QLineEdit{ padding: 0px 10px 0px 10px;}

这设定 padding 的上、右、下、左的宽度,它等效于

QLineEdit{
padding-top:0px;
padding-right:10px;
padding-bottom: 0px;
padding-left:10px;
}

(3) border 是包围 padding 的边框,通过 border 属性 (或 border-width、border-style、border-color)可以定义边框的线宽、线型和颜色,也可以分别定义 border 的上、下、左、右的线宽和颜色。使用border-radius 可以定义边框转角的圆弧半径,从而构造具有圆角矩形的编辑或按钮等组件,例如:

QLineEdit{
border-width: 2px;
border-style: solid;
border-color: gray;
border-radius: 10px;
padding: 0px 10px;
}

这使得 QLineEdit 具有灰色边框线条、圆角矩形的效果。

通过 border-radius、min-width 和 min-height 等属性可以设计圆形的按钮,如:

QPushButton {
    border: 2px groove red;
    border-radius: 30px;
    min-width:60px;
    min-height:60px;
}

使得边框转角半径等于 content 宽度或长度的一半,宽度和长度相等,就可以得到一个圆形的按钮。
使用 border-image 属性还可以为组件设置背景图片,图片会填充 border 矩形框之内的区域,一般使用材质图片设置背景,以使界面具有统一的特色,例如:

QLineEdit,QPushButton{border-image: url(:/images/images/border.jpg);}

(4) margin 是 border 之外与父组件之间的空白边距,可以分别定义上、下、左、右的边距大小。

缺省的情况下,margin、border-width 和 padding 属性缺省值为零,这种情况下,四个同心矩形就是重合的一个矩形。
使用Qt 样式表可以为界面组件设计各种美观的显示效果,美观而特殊的界面不仅需要编程的能力,更重要的是美工设计能力。

3. 样式表的使用

3.1 程序中使用样式表

有多种方法可以应用样式表。
第一种是在使用Qt Designer 设计窗体时,直接用样式表编辑器为窗体或窗体上的某个部件设计样式表,则设计的样式保存在窗体的 ui 文件里,窗体创建时会自动应用所设计的样式表。这样设计的样式表对应用程序是固定的,无法取得换肤的效果,而且需要为每个窗体都设计样式表,重复性工作量太大。
第二种是使用 setStyleSheet 函数应用样式,使用qApp 的 setStyleSheet()函数可以为应用程序全局设置样式,使用QWidget::setStyleSheet()可以为一个窗口、一个对话框或一个界面组件设置样式。例如:

qApp->setStyleSheet("QLineEdit { background-color: gray }");

这里使用应用程序全局变量 qApp 为 QLineEdit 设置样式,如果应用程序内的某些 QLineEdit组件没有再被设置样式,则 QLineEdit 组件的背景色为灰色。

MainWindow->setStyleSheet{ "QLineEdit { background-color: lime }");

这是为主窗口MainWindow 内的QLineEdit 组件设置样式,即背景色为亮绿色

editName->setstyleSheet("color: blue;"
                      "background-color: yellow;"
                      "selection-color: yellow;"
                      "selection-background-color: blue;");

这是设置一个 ObjectName 为 editName 的 QLineEdit 组件的样式,注意这时在样式表中无需设置selector 名称,所设置的样式是应用于editName 这个 QLineEdit 组件的。

**这样将样式表固定在程序中,很显然也是无法实现切换界面效果的。为了实现切换界面效果(换肤)的目的,一般将样式定义表保存为 qss 后缀的纯文本文件,然后在程序中打开文件,读取文本内容,再调用 setStyleSheet()函数应用样式。**示例代码如下:

QFile file(":/qss/mystyle.qss”);
file.open(QFile::ReadOnly);
QString styleSheet = QString::fromLatinl(filereadAll());
qApp->setstyleSheet (styleSheet);

3.2 样式定义的明确性

当多条样式法则对一个属性定义了不同值时,就会出现冲突,例如:

QPushButton#btnSave { color: gray }
QPushButton { color: red }

这两条法则都可以应用于ObiectName 为 btnSave 的QPushButton 组件,都定义了其前景色,这就会出现冲突。这时,选择器的明确性 (specificity) 决定组件适用的样式法则,即法则应用于更明确的组件。

在上面的例子中QPushButton#btSave 被认为是比QPushButton 更明确的选择器因为它指向一个对象,而不是 QPushButton 的所有实例。所以,如果是在一个窗口上应用以上两条法则,则 btnSave 按钮的前景色为 gray,而其他按钮的前景色为red。

同样,具有伪状态的选择器被认为比没有伪状态的选择器明确性更强,如:

QPushButton:hover { color: white }
QPushButton { color: red }

这样,当鼠标在按钮上停留时颜色为 white,否则颜色为 red。
如果两个选择器具有相同的明确性,则以法则出现的先后顺序为准,后出现的法则起作用,例如:

QPushButton:hover { color: white }
QPushButton:enabled { color: red }

这里的两个选择器具有相同的明确性,所以,当鼠标停留在一个使能的按钮上时,只有第二条法则起作用。这种情况下,如果希望不出现冲突,应该修改法则以使其更明确,如下面这两条法则是不冲突的。

QPushButton:hover:enabled { color: white }
QPushButton:enabled { color: red }

父子关系的两个类作为选择器时,具有相同的明确性,例如:

QPushButton { color: red }
QAbstractButton { color: gray }

这两个选择器的明确性相同,所以只依赖于语句的先后顺序
确定法则的明确性,Qt 样式表遵循 CSS2 的规定,在设计样式表时应尽量明确并避免冲突情况。

3.3 样式定义的级联性

样式定义可以在 qApp、窗口或一个具体组件中定义,任何一个组件的样式是其父组件、父窗口和qApp 的样式的融合。当出现冲突时,组件会使用离自己最近的样式定义,即按顺序使用组件自己的样式、或父组件的样式定义、或父窗口的样式定义,或qApp 的样式定义,而不考虑样式选择器的确定性。

例如,在QApplication 中设置全局样式:
qApp->setStyleSheet("QPushButton { color: red }");

那么应用程序中所有未再定义样式的QPushButton 的前景颜色为red。

如果在MainWindow 中再定义样式:
MainWindow->setStyleSheet("QPushButton { color: blue }");
则MainWindow 上的按钮的前景色为 blue,而不是 red。

如果MainWindow上有一个名称为 btnSave的QPushButton 按钮,其定义样式如下:

btnSave->setStyleSheet("color: yellow; background-color: black;");
则按钮 btnSave 按照自己的样式显示前景和背景色。

Qt 样式表功能强大,可以设计自己想要的界面效果,但是这需要有较好的美工设计基础,需要在使用样式表的过程中不断尝试和总结经验。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/64592.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

UE5.2 LyraDemo源码阅读笔记(四)

上一篇(三)讲到在模式玩法UI点击Elimination进入淘汰赛模式。 UI选择点击Elimination后,触发蓝图W_HostSessionScreen的HostSession节点,有: 调用这个方法切换关卡后,会调用到LyraGameMode.cpp的 ALyraGam…

【Gitee的使用】Gitee的简单使用,查看/创建SSH公匙、创建版本库、拉取代码、提交代码

推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享简书地址我的个人博客 大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。 一、前言 本篇文章简单介绍,如何在Gitee上面创建版本库、拉取…

Zookeeper基础操作

搭建Zookeeper服务器 windows下部署 下载地址: https://mirrors.cloud.tencent.com/apache/zookeeper/zookeeper-3.7.1/ 修改配置文件 打开conf目录,将 zoo_sample.cfg复制一份,命名为 zoo.cfg打开 zoo.cfg,修改 dataDir路径&#xff0c…

2023最新性能测试面试题(带答案)

一、性能测试开展过程: 答:第一步:找产品沟通哪些接口需要压测,需要达到什么样的预期值(TPS和响应时间) 第二步:编写测试计划,人员、时间周期、工具 第三步:环境搭建 第四步:造数…

产品缺陷管理软件:了解功能与选择要点

在现代社会,产品缺陷管理软件已经成为了各个行业必不可少的工具。它可以帮助企业更好地管理和解决产品中存在的缺陷问题,提高产品质量和客户满意度。然而,市场上存在着众多的产品缺陷管理软件,如何选择一款好用、适合自己的软件成…

山东气象 × 和鲸科技:第一届齐鲁风云气象智能算法挑战赛圆满收官

7 月 20 日,中国气象局印发《人工智能气象应用工作方案(2023 - 2030年)》,旨在加快布局国产人工智能气象应用技术体系建设,推动人工智能技术在气象观测、预报及服务中的深度融合应用,为监测精密、预报精准、…

word转pdf怎么转?几种常用方法分享

word转pdf怎么转?在日常工作和学习中,将Word文档转换为PDF格式是一项必要的任务。不仅可以保证文档的格式不变,还可以防止文档被他人篡改。但是,Word文档并不是所有人都能够轻松打开和编辑的,而PDF文件则可以在各种设备…

【vue3】vue3和vue2的区别:

文章目录 Vue3框架的优点特点:一、生命周期:二、组合式api(Composition API)三、setup函数四、响应式原理1. 原理2. Object.defineProperty的缺陷3.proxy的优势 五、reactive函数和ref函数1. reactive函数》通常使用它复杂类型的响应式数据2. ref函数》使…

Postman如何做接口测试

目录 Postman如何做接口测试1:如何导入 swagger 接口文档 Postman如何做接口测试2:如何切换测试环境 Postman如何做接口测试3:什么?postman 还可以做压力测试? Postman如何做接口测试4:如何自动添加请求…

【TypeScript】安装的坑!

TypeScript安装 安装TypeScript安装时候可能报错这样开头的数据(无法枚举容器中的对象)——原因:没权限先解决没权限的问题如果发现无法修改-高级-修改继续安装想使用tsc-发现,tsc不能用解决方法:配置环境变量最后的最…

IDEA的实用快捷键大全

目录 1.常规快捷键 1.1通用类 1.2注释类 1.3操作类 1.4展开与关闭 2.智能补全类快捷键 3.程序结构类快捷键 4.统一操作快捷键 1.常规快捷键 1.1通用类 像 Ctrl C 复制, Ctrl V 粘贴, Ctrl S保存文件, Ctrl X剪切,这种…

【VUE】项目本地开启https访问模式(vite4)

在实际开发中,有时候需要项目以https形式进行页面访问/调试,下面介绍下非vue-cli创建的vue项目如何开启https 环境 vue: ^3.2.47vite: ^4.1.4 根据官方文档:开发服务器选项 | Vite 官方中文文档 ps:首次操作,不要被类…

flutter开发实战-flutter_spinkit实现多种风格进度指示器

flutter开发实战-flutter_spinkit实现多种风格进度指示器 最近开发过程中flutter_spinkit,这个拥有多种种风格加载指示器 一、flutter_spinkit 引入flutter_spinkit # 多种风格的模糊进度指示器flutter_spinkit: ^5.1.0效果示例 const spinkit SpinKitRotatingC…

【网络基础实战之路】基于OSPF协议建立两个MGRE网络的实验详解

系列文章传送门: 【网络基础实战之路】设计网络划分的实战详解 【网络基础实战之路】一文弄懂TCP的三次握手与四次断开 【网络基础实战之路】基于MGRE多点协议的实战详解 【网络基础实战之路】基于OSPF协议建立两个MGRE网络的实验详解 PS:本要求基于…

案例:Docker 镜像的创建及使用(commit与dockerfile方式)

文章目录 1、commit方式创建镜像1.1、前期准备1.2、制成镜像1.3、启动镜像1.3.1、启动镜像启动nginx1.3.2、一个命令直接全部启动1.3.3、两种方式区别 1.4、commit创建镜像方式的本质 2、Dockerfile的使用2.1、Dockerfile指令2.2、nginx镜像制作案例2.3、查看构建历史&#xff…

C高级【day4】

思维导图: 写一个函数,获取用户的uid和gid并使用变量接收: #!/bin/bashfunction get_uid {my_uidid -umy_gidid -g }get_uid echo "当前用户的UID:$my_uid" echo "当前用户的GID:$my_gid"整理冒泡…

Object Map 的相互转换

学生业务对象定义&#xff1a;Student Student student new Student(); student.setId(1L); student.setName("令狐冲") student.setAge(10) 第一种&#xff1a;通过Alibaba Fastjson实现 pom.xml 文件依赖 <dependency><groupId>com.alibaba</g…

OpenStreetMap数据转3D场景【Python + PostgreSQL】

很长一段时间以来&#xff0c;我对 GIS 和渲染感兴趣&#xff0c;在分别尝试这两者之后&#xff0c;我决定最终尝试以 3D 方式渲染 OpenStreetMap 中的地理数据&#xff0c;重点关注不超过城市的小规模。 在本文中&#xff0c;我将介绍从建筑形状生成三角形网格、以适合 Blend…

分布式应用:Zabbix监控平台

目录 一、理论 1.Zabbix 2.部署 zabbix 服务端&#xff08;端口号10051&#xff09; 3.部署zabbix 客户端&#xff08;端口号10050&#xff09; 4.将客户端加入服务端的监控主机中 二、实验 1.部署 zabbix 服务端&#xff08;端口号10051&#xff09; 2.部署zabbix 客户…

Nodejs下动态加载文件夹下的文件模块

个人博客 Nodejs下动态加载文件夹下的文件模块 个人博客&#xff0c;求关注&#xff0c;如果有不够清晰的&#xff0c;麻烦指出来&#xff0c;如果有很不正确的&#xff0c;多谢批评。 文章概叙 本文应用的场景是读取指定文件夹下面的所有文件&#xff0c;然后做操作&#…