1+1=10

记记笔记,放松一下...

Qt样式表小记

Qt 样式表(stylesheet),简称QSS,是一种声明式的样式定义方法,允许开发者以类似于 Web 开发中的 CSS 的方式,为 Qt 应用中的传统的QtWidgets窗口控件(如按钮、标签、文本框等)设置外观。它可以用来改变控件的颜色、边框、背景、字体、形状等。

QSS vs CSS

Qt 样式表 与 CSS2 在语法和部分功能上有很多相似之处,但 Qt 样式表 是为桌面应用的 Qt Widgets 设计的,功能和灵活性相比 CSS2 有一些限制。

特性 Qt 样式表 CSS2
适用对象 用于 Qt Widgets(桌面应用的控件) 用于 HTML 元素(网页中的元素)
选择器支持 支持CSS2所有选择器类型 -
子控件选择器 专门引入了 ::subcontrol 来选择控件的子部分 直接使用类或 ID 选择器
继承性 通过合并祖先控件和应用程序的样式表来获得。不会自动从父窗口的继承颜色字体等。没有 !important 规则 样式在父子元素之间可以继承(如 colorfont-size 等)
单位支持 px(通用)、pt(只用于字体)、emex 完全支持 pxemrem% 等多种单位
背景图片 支持 background-imageborder-image 支持 background-image,可用于更多元素和伪类
颜色 支持颜色名称和十六进制颜色值,如 #RRGGBB以及hsv,hsl等 。注意Qt有调色版palette可供使用。具体关注属性类型Brush。 没有调色板
渐变色 qlineargradient等,与CSS语法差异大 linear-gradient
边框样式 支持 border,但不支持如 border-collapse 等复杂的属性 支持完整的边框属性,如 border-radiusborder-collapse
属性值支持 支持基本的属性值,如 colorbackground-colorborder 支持更复杂的属性值,如 box-shadowtext-shadow

另外注意Qt特有的语法:

子控件(Sub-Controls)

子控件(Sub-control) 是 Qt 中用于样式化复杂控件的一个重要概念。它们可以通过双冒号::语法进行选择,并且可以使用 subcontrol-originsubcontrol-position 来调整其在小部件中的定位。

对于 QComboBox 的下拉按钮。选择器可以包含子控件,从而使得可以将样式规则应用于特定的子控件。例如:

1
2
3
4
5
6
7
QComboBox {
    margin-right: 20px;
}
QComboBox::drop-down {
    image: url(dropdown.png);
    subcontrol-origin: margin;
}

双冒号 :: 语法类似 CSS3 的伪元素,二者概念上有不同,且具有不同的层叠语义。

C++命名空间中的控件

Qt 样式表使用控件的 QObject::className() 来确定类型选择器。如果自定义的控件位于命名空间中,QObject::className() 将返回 <namespace>::<classname>。这与子控件(Sub-Controls)的语法相冲突。为了解决这个问题,当为命名空间中的小部件使用类型选择器时,必须将 :: 替换为 --

1
2
3
4
5
6
7
namespace ns {
    class MyPushButton : public QPushButton {
        // ...
    }
}

qApp->setStyleSheet("ns--MyPushButton { background: yellow; }");

Q_PROPERTY属性

QSS 提供了一个特性,允许通过 qproperty- 前缀直接设置控件的 Qt 属性。这在 CSS 中是不存在的,主要是为了与 Qt 对象属性系统 进行集成。

1
2
3
4
QPushButton {
    qproperty-icon: url(icon.png);
    qproperty-iconSize: 32px;
}

通过Q_PROPERTY 定义的属性都可以使用 qproperty-<属性名> 语法进行设置。

QSS模板

网络上不少网友分享的qss模板以及和模板相关的工具

模板

  • https://qss-stock.devsecstudio.com/
  • https://github.com/GTRONICK/QSS
  • https://github.com/githubuser0xFFFF/Qt-Advanced-Stylesheets
  • https://github.com/ColinDuquesnoy/QDarkStyleSheet
  • https://github.com/Jorgen-VikingGod/Qt-Frameless-Window-DarkStyle
  • https://www.tech-artists.org/t/release-qt-dark-orange-stylesheet/2287
  • https://github.com/antonypro/QGoodWindow

工具

QSS没有原生的 theme(主题) 或 SASS 等预处理器的直接支持。但有不少工具来做这样的事情

  • https://github.com/hustlei/QssStylesheetEditor
  • https://github.com/HappySeaFox/qsseditor
  • https://github.com/UN-GCPDS/qt-material
  • https://gitlab.com/pavel.krupala/qt-skin-generator
  • https://github.com/Qt-Widgets/Qui_QSS_Skin_Builder

样式切换的一些思考点

我们可以使用SASS方式编写文件:

1
2
3
4
5
6
7
$button-bg-color: #333;
$button-text-color: white;

QPushButton {
    background-color: $button-bg-color;
    color: $button-text-color;
}

而后调用sass或者使用其他三方工具生成qss样式表。这样,调整变量,容易生成多套样式表(尽管是静态的)。

另外,考虑调色板可以用,可以让其作为QSS基本色

1
2
3
4
5
6
QToolTip{
  color:#ffffff;
  background-color:palette(base);
  border:1px solid palette(highlight);
  border-radius:4px;
}

这样Qt程序运行时通过代码中修改调色板来影响样式表。

控件的动态属性(setProperty)配合QSS的属性选择器,也容易实现单个qss文件的主题切换。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
qApp->setStyleSheet(R"(
    QPushButton[theme="dark"] {
        background-color: #333;
        color: white;
    }
    QPushButton[theme="light"] {
        background-color: #fff;
        color: black;
    }
)");

对于样式表不能直接控制的部分,我们可以使用qproperty- 语法自定义属性进行补充。

1
2
3
4
QPushButton {
    qproperty-iconSize: 24px;
    qproperty-flat: true;
}

参考

Qt Qt