编程与调试 C++ -- Qt QSS 代码编写规范
基础知识
样式表由一系列样式规则组成,样式规则由选择器和声明组成。
/* 选择器 */
QPushButton {
/* 声明 */
color: red;
/* 声明 */
width: 20px;
}
选择器类型
选择器 | 示例 | 说明 |
---|---|---|
通用选择器 | * | 匹配所有部件。 |
类型选择器 | QPushButton | 匹配所有 QPushButton 实例和它的所有子类。 |
属性选择器 | QPushButton[flat="false"] | 匹配 QPushButton 的属性 flat 为 false 的实例。 |
类选择器 | .QPushButton | 匹配所有 QPushButton 实例,但不包含它的子类。 |
ID 选择器 | QPushButton#okButton | 匹配所有 QPushButton 中以 okButton 为对象名的实例。 |
后代选择器 | QDialog QPushButton | 匹配所有 QPushButton 实例,它们必须是 QDialog 的子孙部件。 |
孩子选择器 | QDialog>QPushButton | 匹配所有 QPushButton 实例,它们必须是 QDialog 的直接子部件。 |
子控件
一些复杂空间具有子控件,如 QComboBox 的下拉按钮,QSpinBox 的上下箭头,可以指定子控件的样式。
QComboBox::drop-dpwn {
image:url(:img/res/toolBar/start/btn_zoom_nor.png);
}
伪状态
部分部件具有状态,如 hover,pressed 等,选择器可以包含伪状态来限制规则在部件的指定状态上应用。
QPushButton:hover {
color: blue;
}
QPushButton:pressed {
color: yellow;
}
Qt 中,控件支持的声明属性,子控件和伪状态,可以在 Qt 的帮助文档中搜索 Qt Style Sheets Reference 关键字了解。
规范建议
目前,项目中的样式表统一写到 styleSheet.qss
中,方便查阅修改。以往的代码可能存在一定的规范问题,建议新入库的样式遵循下列规则。
对所有控件重新命名
对于一些代码不会操作的控件,比如某些 label,Qt Designer 会自动起名,如 label_2、label_3 等,容易与其他窗口中的控件名重复。
若 QSS 编码不规范,可能导致影响到其他窗口的同名控件。若不好起名,可以增加父控件的前缀,如 settingDlgLabel_2、settingDlgLabel_3。
必须使用后代选择器,即指定控件的父控件
若只使用 ID 选择器,是极为危险的行为,全局范围内任何同名的控件都会受到影响,尤其没有修改控件默认命名的情况。
/* 非常危险 */
#label_2 {
color: red;
}
/* 正确写法 */
SettingDlg #settingDlgLabel_2 {
color: red;
}
注意,在某些情况下,你使用的是类型选择器 + ID 选择器,并没有使用后代选择器。
/* 类型选择器 + ID 选择器 */
QLabel #settingDlgLabel_2 {
color: red;
}
/* 正确写法 */
SettingDlg QLabel #settingDlgLabel_2 {
color: red;
}
谨慎使用逗号分隔
使用逗号对选择器进行分组时,一定要注意重新指定父控件,否则会导致全局的改变。
/* 错误 */
SettingDlg #settingDlgLabel_2, #settingDlgLabel_3 {
color: red;
}
/* 正确写法 */
SettingDlg #settingDlgLabel_2, SettingDlg #settingDlgLabel_3 {
color: red;
}
/* 错误 */
SettingDlg QComboBox, QSpinBox {
color: red;
}
/* 正确写法 */
SettingDlg QComboBox, SettingDlg QSpinBox {
color: red;
}
格式规范
- 选择器之间,{ 之前,需要填充空格。
- 属性的定义必须另起一行。
- { 不换行。
- 属性之前用 4 空格 缩进。
- 参考 Google CSS 规范中的其他条例。
/* 错误:{ 启了新行 */
SettingDlg #settingDlgLabel_2
{
color: red;
}
/* 错误:{ 前需要空格 */
SettingDlg #settingDlgLabel_2{
color: red;
}
/* 错误:属性需要新启行 */
SettingDlg #settingDlgLabel_2 { color: red; }
/* 错误:属性需要缩进 */
SettingDlg #settingDlgLabel_2 {
color: red;
}
/* 正确写法 */
SettingDlg #settingDlgLabel_2 {
color: red;
}
Stylesheet Performance Hits with Qt
Stylesheet Performance Hits with Qt
qApp->style()->unpolish(this); // "this" is my main window
qApp->style()->polish(this);
this->update();
QWidgetList all = allWidgets();
// unpolish all
for (QWidgetList::ConstIterator it = all.constBegin(), cend = all.constEnd(); it != cend; ++it) {
QWidget *w = *it;
if (!(w->windowType() == Qt::Desktop) && // except desktop
w->testAttribute(Qt::WA_WState_Polished)) { // has been polished
m_app->style()->unpolish(w);
}
}
m_app->style()->unpolish(qApp); // 这行可能很重要。
// repolish all
for (QWidgetList::ConstIterator it = all.constBegin(), cend = all.constEnd(); it != cend; ++it) {
QWidget *w = *it;
if (w->windowType() != Qt::Desktop && w->testAttribute(Qt::WA_WState_Polished)) {
if (w->style() == m_app->style())
m_app->style()->polish(w); // repolish
else
w->setStyleSheet(w->styleSheet()); // touch
}
}
// re event
for (QWidgetList::ConstIterator it = all.constBegin(), cend = all.constEnd(); it != cend; ++it) {
QWidget *w = *it;
if (w->windowType() != Qt::Desktop && !w->testAttribute(Qt::WA_SetStyle)) {
QEvent e(QEvent::StyleChange);
QApplication::sendEvent(w, &e);
w->update();
}
}
参考资料快照
参考资料快照