QSS(Qt Style Sheets)是Qt样式表,与制作前端web中使用CSS来美化网页一样, QSS为Qt提供属性、伪状态、子控件等机制来自定义控件外观。对于设计Qt应用程序,QSS是必须掌握的,因为它能让你付出最少的代价,美化应用程序。而不用去继承QWidget,做很多复杂的工作(当然我们不是说这种方式不重要,后面会介绍这种方式,并且以实现ribbon为目标)。另外,QtQuick和QGraphicsView能够定制更好的用户体验,后面再一点点体验和分享给大家。
工欲善其事,必先利其器,一款好的编辑器有利于快速编写所需样式。
Qt Creator
Qt Creator默认是不会高亮qss内容,这个只需要配置一下:
*.qss
,即将原来的“模式”改为:*.css;*.CSSL;*.qss
。QSS Editor
QSS Editor可以预览,没有语法提示。
Kineticwing IDE
KiWi 是一款智能、轻便、便携的 IDE,可以更快捷、更轻松的进行 WEB 开发。支持 HTML、CSS、QSS、SASS、JavaScript、PHP、XML、ASP、Perl 等。
对 QSS 的支持,主要包含以下功能:
代码突出显示(语法着色)
括号高亮显示(当光标位于包含字符的开始和结束之间时,编辑器会成对突出显示大括号)
折叠代码段
保存状态标记(绿色是保存状态,红色是未保存状态)
智能自动完成
缺点:无法实时预览。
QSS 包含了一个样式规则序列,术语和语法规则几乎和CSS相同。
QSS包含了一个样式规则序列,一个样式规则由一个选择器和声明组成,选择器指定哪些部件由规则影响,声明指定哪些属性应该在部件上进行设置。例如:
QPushButton { color: red }
上面的例子中QPushButton是选择器,{ color: red }是声明,该规则指定QPushButton及其子类(例如:MyPushButton)应使用红色作为前景色。
QSS通常不区分大小写(即:color、Color、COLOR、cOloR指同一属性),唯一例外就是类名(class names)、对象名(object names)、属性名(property names)区分大小写。
几个选择器可以指定相同的声明,使用逗号(,)来分隔选择器。例如:
QPushButton, QLineEdit, QComboBox { color: red }
等价于
QPushButton { color: red }
QLineEdit { color: red }
QComboBox { color: red }
声明部分的规则是一个属性值对(property: value)列表,包含在花括号中,以分号分隔。例如:
QPushButton { color: red; background-color: white }
更多声明规则,可以查阅Qt文档,Qt Style Sheets Reference中List of Properties部分,
或是直接查阅在线文档Qt Style Sheets Reference
选择器类型
选择器 | 例子 | 详细描述 |
---|---|---|
通用选择器 | * | 匹配所有控件 |
类型选择器 | QPushButton |
匹配QPushButton 实例和其子类 |
属性选择器 | QPushButton[flat="false" ] |
匹配QPushButton中flat属性为false的实例。可以用此选择器来测试任何支持QVariant::toString()的属性,此外,支持特殊的类属性、类名称。此选择器也可以用来测试动态属性(参考助手:Qt Style Sheets Examples中Customizing Using Dynamic Properties部分)。还可以使用~=替换=,测试QStringList类型的属性是否包含给定的QString。 警告:如果Qt属性值在设置样式之后更改,那么可能需要强制重新计算样式。实现的一个方法是取消样式,然后重新设置一遍。 |
类选择器 | .QPushButton |
匹配QPushButton 实例,但是不包括其其子类。其等价于 *[class~="QPushButton"] |
ID选择器 | QPushButton#okButton |
匹配所有对象名为“okButton”的QPushButton 实例 |
后代选择器 | QDialog QPushButton |
匹配所有属于QDialog后代(子部件,孙子部件…)的QPushButton 实例 |
子选择器 | QDialog > QPushButton |
匹配所有属于QDialog直接子部件的QPushButton 实例 |
QComboBox
的下拉按钮,或QSpinBox
递增邪恶向上箭头和递减的向下箭头。选择器应该包含子控件,让他可以限制指定控件的副控件的应用规则。例如:QComboBox::drop-down { image: url(dropdown.png) }
QComboBox {
margin-right: 20px;
}
QComboBox::drop-down {
subcontrol-origin: margin;
}
下拉框在边框内的对齐方式,可以通过subcontrol-position属性改变。
高度和宽度属性可以控制子控件的尺寸,
【注意】设置图片的大小会隐式的改变子控件的大小,这个比较重要,你试着用32px的icon作为控件的图标,工作在1920x1080的屏幕上。 当换成4k屏(4096×2160)时,你的所有控件都变小,缩成一堆。解决方案(根据像素换成大图标,没有去实践,手上没有4K屏)…这个问题找到准确解决方案在补上。
相对位置方案 (position : relative
), 即允许子控件相对于其初始位置做偏置。例如: QComboBox
下拉按钮被按下时,我们可以使其内部的下拉箭头在做一些偏置,达到被按下的效果。具体实现如下:
QComboBox::down-arrow {
image: url(down_arrow.png);
}
QComboBox::down-arrow:pressed {
position: relative;
top: 1px; left: 1px;
}
绝对位置方案 (position : absolute
),允许相对于参考元素改变子控件位置和大小。
一旦位置被设定,这些子控件将被和普通部件(widgets)视为相同,并且可以使用盒模型样式(参考助手:Customizing Qt Widgets Using Style Sheets中The Box Model部分)。
**注意:**对于复杂的部件,如:QComboBox和QScrollBar,如果一个属性或子控件被定制,所有其它属性或子控件必须被定制好。
选择器可以包含伪状态,表示基于控件的状态限制应用程序的规则。伪状态出现在选择器后面,用冒号(:)关联。例如下面的应用规则,鼠标划过按钮:
QPushButton:hover { color: white }
伪状态可以用取反声明符(!)表示否定,例如下面的应用规则,鼠标没有经过QRadioButton
上方:
QRadioButton:!hover { color: red }
伪状态可以连接使用,用冒号(:)将所有伪状态连起来,相当于逻辑与(AND)操作符。例如:鼠标经过一个被选中的按钮。
QCheckBox:hover:checked { color: white }
伪状态链中可以有取反(!)的伪状态,例如:鼠标经过一个没有被按下的按钮
QPushButton:hover:!pressed { color: blue; }
如果需要,逻辑或(OR)可以被表示成逗号(,)
QCheckBox:hover, QCheckBox:checked { color: white }
伪状态可以用在子控件中,例如:
QComboBox::drop-down:hover { image: url(dropdown_bright.png) }
更加详细可以参考助手:Qt Style Sheets Reference中List of Pseudo-States部分。
QPushButton#okButton { color: gray }
QPushButton { color: red }
两个规则都匹配到对象名为okButton
的 QPushButton
实例,那么color
这个属性有冲突,所以必须考虑两个选择器的特殊性。对象名为okButton
的 QPushButton
实例是比QPushButton
特殊,因为他通常指的一个对象,而不是所有QPushButton
对象。
QPushButton
时,使用的应该时白色的文本QPushButton:hover { color: white }
QPushButton { color: red }
QPushButton
文本颜色为红色QPushButton:hover { color: white }
QPushButton:enabled { color: red }
如果要设置QPushButton
文本颜色为白色,只需要将上面白色的属性样式放到最后,如下所示:
QPushButton:enabled { color: red }
QPushButton:hover { color: white }
或者使QPushButton
前景为白色属性的样式更加特殊,如下所示
#添加了enabled的伪状态
QPushButton:hover:enabled { color: white }
QPushButton:enabled { color: red }
QPushButton { color: red }
QAbstractButton { color: gray }
上面的两条样式规则都会作用于QPushButton
(自从QPushButton
继承 QAbstractButton
), 那这里就有颜色属性的争执。 因为QPushButton
继承 QAbstractButton
,则认为QPushButton
比QAbstractButton
更加具有特殊性。
当然,对于样式的计算,所有拥有相同特殊性的类型的选择器,则顺序在最后的样式优先。或者说,所有QAbstractButtons
的前景颜色都设置为灰色,包括QPushButtons
。如果我们真正想 QPushButtons
设置为红色的前景,我们可以把描述样式的规则重新排序。
* {} /* a=0 b=0 c=0 -> specificity = 0 */
LI {} /* a=0 b=0 c=1 -> specificity = 1 */
UL LI {} /* a=0 b=0 c=2 -> specificity = 2 */
UL OL+LIa {} /* a=0 b=0 c=3 -> specificity = 3 */
H1 + *[REL=up]{} /* a=0 b=1 c=1 -> specificity = 11 */
UL OL LI.red {} /* a=0 b=1 c=3 -> specificity = 13 */
LI.red.level {} /* a=0 b=2 c=1 -> specificity = 21 */
#x34y {} /* a=1 b=0 c=0 -> specificity = 100 */
级联
样式可以说被设置在 QApplication
, 在父控件,子控件。任意控件的有效样式可以通过合并其祖先的(父级,祖父级等)以及 QApplication
上设置的样式获得。
考虑这样的一个结果,自动设置一个控件样式规则,它的优先级高于其祖先或者 QApplication
的样式规则规则。 如下,为 QApplication
设置样式表
qApp->setStyleSheet("QPushButton { color: white }");
然后我们为QPushButton
对象设置样式,如下所示:
myPushButton->setStyleSheet("* { color: blue }");
QPushButton
的样式就会迫使QPushButton
(以及它的子控件)前景文本为蓝色。尽管应用程序范围内提供了更多特殊的规则,但QPushButton
(以及它的子控件)并不会使用。
如果按照下面这种方式写,其结果是相同的:
myPushButton->setStyleSheet("color: blue");
除非 QPushButton
有子控件,那么这个样式将不会影响到。不过一般QPushButton
不会有子控件。
样式极联是一个复杂的主题。请参考CSS2 Specification,请注意,目前Qt没有实现。
继承
在经典的CSS中,当字体和颜色等项目没有显式设置,它会自动继承父级控件的样式。默认情况下,在QSS中,一个控件是不会自动继承它父级控件的字体和颜色的设置。
例如: QGroupBox
里面的子控件QPushButton
:
qApp->setStyleSheet("QGroupBox { color: red; } ");
QPushButton
没有显式设置颜色, 因此,QPushButton
设置为系统的颜色,而没有继承它的父级控件颜色。如果我们想设置QGroupBox
及其子级控件的样式,我们可以这么写:
qApp->setStyleSheet("QGroupBox, QGroupBox * { color: red; }");
于此相比,可以使用 QWidget::setFont()
和 QWidget::setPalette()
设置字体和调色板用到子控件中。
如果你想字体和调色板可以传播到子控件,可以设置这个标志: Qt::AA_UseStyleSheetPropagationInWidgetStyles
使用方法:
QCoreApplication::setAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles, true);
当控件风格中字体和调色板的传播使能,字体和调色板通过QSS所做的更改将会执行,即使用户手动调用对应 QWidget::setPalette()
和 QWidget::setFont()
的方法在所有QWidgets 所针对的样式目标。
控件在NameSpace中
类型选择器可以被用于特定的控件风格。例如:
class MyPushButton : public QPushButton {
// ...
}
// ...
qApp->setStyleSheet("MyPushButton { background: yellow; }");
Qt 样式使用控件的类名(QObject::className()
)来决定是否应用类型选择器。当自定义的控件在命名空间中(namespaces), 类名(QObject::className()
)返回<namespace>::<classname>
。这个命名方式于子控件的样式规则命名方式有冲突。为了克服这个问题,当空间选择器在命名空间内时,我们使用“–”替代“::”。如下所示:
namespace ns {
class MyPushButton : public QPushButton {
// ...
}
}
// ...
qApp->setStyleSheet("ns--MyPushButton { background: yellow; }");
子控件的样式规则,如果命名空间的表示方式不做更改,那就会发生冲突:
QComboBox::down-arrow {
image: url(down_arrow.png);
}
QObject
的属性Q_PROPERTY
都可以使用 qproperty-<property name>
的语法。如下例子:MyLabel { qproperty-pixmap: url(pixmap.png); }
MyGroupBox { qproperty-titleColor: rgb(100, 200, 100); }
QPushButton { qproperty-iconSize: 20px 20px; }
如果属性参考 Q_ENUMS
的枚举声明,我们应该参考它常量的名字,而不是数值。
文章浏览阅读101次。4.class可以有⽆参的构造函数,struct不可以,必须是有参的构造函数,⽽且在有参的构造函数必须初始。2.Struct适⽤于作为经常使⽤的⼀些数据组合成的新类型,表示诸如点、矩形等主要⽤来存储数据的轻量。1.Class⽐较适合⼤的和复杂的数据,表现抽象和多级别的对象层次时。2.class允许继承、被继承,struct不允许,只能继承接⼝。3.Struct有性能优势,Class有⾯向对象的扩展优势。3.class可以初始化变量,struct不可以。1.class是引⽤类型,struct是值类型。
文章浏览阅读586次。想实现的功能是点击顶部按钮之后按关键字进行搜索,已经可以从服务器收到反馈的json信息,但从json信息的解析开始就会闪退,加载listview也不知道行不行public abstract class loadlistview{public ListView plv;public String js;public int listlength;public int listvisit;public..._rton转json为什么会闪退
文章浏览阅读219次。如何使用wordnet词典,得到英文句子的同义句_get_synonyms wordnet
文章浏览阅读521次。系统项目报表导出 导出任务队列表 + 定时扫描 + 多线程_积木报表 多线程
文章浏览阅读1.1k次,点赞9次,收藏9次。使用AJAX技术的好处之一是它能够提供更好的用户体验,因为它允许在不重新加载整个页面的情况下更新网页的某一部分。另外,AJAX还使得开发人员能够创建更复杂、更动态的Web应用程序,因为它们可以在后台与服务器进行通信,而不需要打断用户的浏览体验。在Web开发中,AJAX(Asynchronous JavaScript and XML)是一种常用的技术,用于在不重新加载整个页面的情况下,从服务器获取数据并更新网页的某一部分。使用AJAX,你可以创建异步请求,从而提供更快的响应和更好的用户体验。_ajax 获取http数据
文章浏览阅读2.8k次。登录退出、修改密码、关机重启_字符终端
文章浏览阅读3.8k次,点赞3次,收藏51次。前段时间看到一位发烧友制作的超声波雷达扫描神器,用到了Arduino和Processing,可惜啊,我不会Processing更看不懂人家的程序,咋办呢?嘿嘿,所以我就换了个思路解决,因为我会一点Python啊,那就动手吧!在做这个案例之前先要搞明白一个问题:怎么将Arduino通过超声波检测到的距离反馈到Python端?这个嘛,我首先想到了串行通信接口。没错!就是串口。只要Arduino将数据发送给COM口,然后Python能从COM口读取到这个数据就可以啦!我先写了一个测试程序试了一下,OK!搞定_超声波扫描建模 python库
文章浏览阅读4.2k次。端—端加密指信息由发送端自动加密,并且由TCP/IP进行数据包封装,然后作为不可阅读和不可识别的数据穿过互联网,当这些信息到达目的地,将被自动重组、解密,而成为可读的数据。不可逆加密算法的特征是加密过程中不需要使用密钥,输入明文后由系统直接经过加密算法处理成密文,这种加密后的数据是无法被解密的,只有重新输入明文,并再次经过同样不可逆的加密算法处理,得到相同的加密密文并被系统重新识别后,才能真正解密。2.使用时,加密者查找明文字母表中需要加密的消息中的每一个字母所在位置,并且写下密文字母表中对应的字母。_凯撒加密
文章浏览阅读5.7k次。CIP报文解析常用到的几个字段:普通类型服务类型:[0x00], CIP对象:[0x02 Message Router], ioi segments:[XX]PCCC(带cmd和func)服务类型:[0x00], CIP对象:[0x02 Message Router], cmd:[0x101], fnc:[0x101]..._cip协议embedded_service_error
文章浏览阅读2.4k次,点赞9次,收藏13次。有时候我们在MFC项目开发过程中,需要用到一些微软已经提供的功能,如VC++使用EXCEL功能,这时候我们就能直接通过VS2019到如EXCEL.EXE方式,生成对应的OLE头文件,然后直接使用功能,那么,我们上篇文章中介绍了vs2017及以前的版本如何来添加。但由于微软某些方面考虑,这种方式已被放弃。从上图中可以看出,这一功能,在从vs2017版本15.9开始,后续版本已经删除了此功能。那么我们如果仍需要此功能,我们如何在新版本中添加呢。_vs添加mfc库
文章浏览阅读785次。用ac3编码,执行编码函数时报错入如下:[ac3 @ 0x7fed7800f200] frame_size (1536) was not respected for anon-last frame (avcodec_encode_audio2)用ac3编码时每次送入编码器的音频采样数应该是1536个采样,不然就会报上述错误。这个数字并非刻意固定,而是跟ac3内部的编码算法原理相关。全网找不到,国内音视频之路还有很长的路,音视频人一起加油吧~......_frame_size (1024) was not respected for a non-last frame
文章浏览阅读230次,点赞2次,收藏2次。创建Android应用程序一个项目里面可以有很多模块,而每一个模块就对应了一个应用程序。项目结构介绍_在安卓移动应用开发中要在活动类文件中声迷你一个复选框变量