Qt样式表踩坑小记

发布时间 2023-05-28 20:44:06作者: 桑底坡

在一个项目里使用样式表修饰界面,最终实现的效果不错,坑也踩了不少,浪费好几天时间。

坑 1 :样式表的字符集。

这个问题只在MSVC里出现,使用MinGW应该不会出现这个问题。qt的默认字符集是utf8,但msvc要求源码必须是ANSI或者带BOM的Utf8,所以一般我们在做msvc项目时,把Qt环境配置编辑器->文本->
行为->utf8-bom选项,改为Add If encoding Is Utf-8,这样默认保存的格式msvc才可以正常编译。直接从MinGW项目复制过来的文件无法编译,因为msvc无法正常解析非Bom的utf8。
文件都以utf8-bom保存之后,msvc可以正常编译,但同时样式表的问题就出来了。
本来样式表是好使的,然后不知怎么突然就不好使。各种尝试,各种排查,最后发现是字集的问题。qt在解析样式表的时候不认utf8-bom,他把文件开头的bom识别成一个特殊字符,然后整个样式表就全部失效。
解决办法起初使用第三方编辑器把css文件保存成utf8或者ANSI格式,每次修改都这么操作太麻烦,最后用QCodec解决一下。

QFile qssFile(":/style.css");//样式表保存在资源文件
if(qssFile.open(QFile::ReadOnly))
{
//原始格式读出
QString qss = QString::fromLatin1(qssFile.readAll());
//生成一个GBK编码器
QTextCodec *codec = QTextCodec::codecForName("GBK");
//从unicode转换为gbk
QString qs = QString(codec->fromUnicode(qss));
//整个app都使用此样式表

qApp->setStyleSheet(qs);
qssFile.close();
}
这样用内置编辑器可以直接编辑 css文件,直接保存不需要额外处理。

坑 2 :自定义组件样式表无效

这是一个动态管理的界面,程序运行时读取配置文件,根据配置文件确定界面显示内容。为简化构造界面的代码,我把几个固定搭配的组件封装成单独的类,但系统样式表对自定义组件类里的成员不起作用。上网检索,得到答案是自定义类需要实现一下重绘事件。

#include <QStyleOption>
#include <QPainter>
.
.
.

void MyClass::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
QStyleOption opt;
opt.init(this);
QPainter p(this);
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}

坑 3 :样式表写的到处都是

发生这个问题主要是因为前面排错没头绪又赶时间,为了实现效果就在代码里需要样式表的地方直接用了Widget->setStyleSheet(.....);这样的写法。
在解决坑 1和坑2 问题之后,样式表是起了作用,但实际运行结果乱的一团糟,毫无规律 。于是拆除了所有夹在代码里的setStyleSheet,终于一切都正常。

本来我理解这个样式表的层叠,应该是后的覆盖前的,同一个组件,后来定义的时候只写和前面不一样的就行,但程序代码夹进样式表之后就不是这样了。

 

另外,如果自定义组件成员需要单独设置,可以用下面几种写法,以QPushButton为例。

MyClass QPushButton{...}
MyClass > QPushButton{...}

还可以在自定义类中生成Widget后进行设置一个属性,比如有个名字pb1的按钮,
pb1->setProperty("myButton","config");

在css文件里可以用
QPushButton[myButton="config"]{}
的写法访问。

但是MyClass QPushButton#pb1{...}
这样的写法无效。