常规加载的情况:项目简单只需要读取一个qss文件,或者根据不同需要在不用情况下读取多个qss文件中的一个文件。
#include
Tip::Tip(QWidget *parent) :
QDialog (parent),
ui(new Ui::Tip)
{
ui->setupUi(this);
QFile qss(":/qss/qss_light.qss");
if (qss.open(QFile::ReadOnly)){
qApp->setStyleSheet( qss.readAll());
}
}
具体代码:
void LoadStyle::LoadStyleFile(QString strStyle)
{
QFile qss(strStyle);
qss.open(QFile::ReadOnly);
qApp->setStyleSheet(qss.readAll());
qss.close();
}
在主界面初始化时,调用这个函数,并把资源文件也就是QSS文件路径传进去:
m_cLoadStyle.LoadStyleFile(":/CTreeWidgetPro/Resource/Qss/CTreeWidgetPro.qss");
m_cLoadStyle.LoadStyleFile(":/CTreeWidgetPro/Resource/Qss/CustomItem.qss");
加载所有QSS文件大致思路是将QSS文件所在的文件夹下的所有样式文件都一次获取,循环读文件里面的内容,然后保存在一个字符串变量中,最后直接调用qApp->setStyleSheet()这个函数。
void LoadStyle::LoadStyleFile()
{
QString strDirPath = ":/CTreeWidgetPro/Resource/Qss";
QStringList strListStyleFiles = QDir(strDirPath).entryList(QDir::Files);
QString strStyle = GetAllStyle(strListStyleFiles, strDirPath);
qApp->setStyleSheet(strStyle);
}
QString LoadStyle::GetAllStyle(QStringList strListStyleFiles, QString strDirPath)
{
if (!strDirPath.endsWith("/"))
{
strDirPath.append("/");
}
QString strStyle;
for (auto strFileName : strListStyleFiles)
{
QFile fileRead(strDirPath + strFileName);
if (fileRead.open(QFile::ReadOnly))
{
strStyle += QLatin1String(fileRead.readAll());
}
fileRead.close();
}
return strStyle;
}
LoadStyleFile()函数中,strDirPath变量是QSS文件所在的文件夹;strListStyleFiles保存了文件夹下面所有文件的文件名称;
GetAllStyle()函数中,在for循环中处理每一个文件名,将文件夹路径+文件名就组成了完整了QSS文件路径,在进行读操作,将所有的文件读完之后保存并返回。
m_cLoadStyle.LoadStyleFile();
最后只要在主界面调用这个LoadStyleFile();函数即可:
m_cLoadStyle是加载资源文件类的对象,不管资源文件夹下面多少个QSS样式文件,都只需要调用一次即可,后续资源文件中继续添加新的QSS文件,这部分代码也不用进行修改。
软件QssEditor的样式编辑器,他里面有一种很神奇的颜色用法。
QLabel {
color:#FF0000;
}
QPushButton{
color:#FF0000;
}
假如我有一个红色字体软件,现在有个场景需要把红色都改成绿色。
QLabel {
color:#00FF00;
}
QPushButton{
color:#00FF00;
}
正常做法是准备两份样式red.qss和green.qss,需要什么颜色我就加载什么样式。
但是借鉴下QssEditor里面的做法,就是用theme值替换原有值
QLabel {
color:$FontColor;
}
QPushButton{
color:$FontColor;
}
在代码里面把$FontColor替换成对应颜色
QFile file("style.qss");
if (file.open(QIODevice::ReadOnly))
{
QMap<QString, QString> theme;
theme.insert("$FontColor", "#FF0000");
QString style = file.readAll();
for(const QString& key : theme)
{
style.replace(key, theme[key]);
}
qobject_cast<QApplication*>(QApplication::instance())->setStyleSheet(style);
file.close();
}
如果是theme更改成全局变量,可以达到程序即使在运行中,也可以动态去修改颜色。
在大胆点使用的话,是不是可以将整按钮的样式都替换theme值
QLabel {
color:#FF0000;
}
$ButtonStyle
把button的样式单独写成一份button.qss,在通过QFile写入到对应theme值
QFile file("style.qss");
if (file.open(QIODevice::ReadOnly))
{
QMap<QString, QString> theme;
QFile f("button.qss");
if (f.open(QIODevice::ReadOnly))
{
theme.insert("$ButtonStyle", f.readAll());
}
else {
theme.insert("$ButtonStyle", "");
}
QString style = file.readAll();
for(const QString& key : theme)
{
style.replace(key, theme[key]);
}
qobject_cast<QApplication*>(QApplication::instance())->setStyleSheet(style);
file.close();
}
那这样操作的话,一个类型的控件我就单独封装成一个qss样式文件,在集中替换到style.qss文本。
是不是只需要一个配置单,配置好每个theme值对应的qss样式文件名
$LabelStyle=label.qss
$ButtonStyle=button.qss
...
这样就代码只需要加载一个配置单和一个style.qss文件就可以,其他的控件样式文件动态的加载到界面上。
注意,如果样式中出现theme值没被正确替换,会导致theme值之后的所有样式失效。
下面就可以正式版本
#include
#include
#include
#include
#include
#include
#include
#define STYLE_SHEET_PATH "style.qss"
#define STYLE_SHEET_CONFIG "style.ini"
void realRefreshTheme(QString &style)
{
QMap<QString, QString> theme;
QSettings settings(STYLE_SHEET_CONFIG);
for(const QString& key : settings.allKeys())
{
const QString &path = settings.value(key).toString();
QFile file(path);
if (file.open(QIODevice::ReadOnly))
{
theme.insert(key, file.readAll());
}
else {
theme.insert(key, "");
}
}
for(const QString& key : theme.keys())
{
style.replace(key, theme[key]);
}
}
void realRefreshStyle()
{
static QTimer timer;
#ifdef QT_DEBUG
timer.setSingleShot(false);
#else
timer.setSingleShot(true);
#endif
QObject::connect(&timer, &QTimer::timeout, []() {
static QDateTime dateTime;
QFileInfo fileInfo(STYLE_SHEET_PATH);
if (fileInfo.exists())
{
QDateTime fileTime = fileInfo.lastModified();
if (dateTime == fileTime)
return;
dateTime = fileTime;
QFile file(STYLE_SHEET_PATH);
if (file.open(QIODevice::ReadOnly))
{
QString style = file.readAll();
realRefreshTheme(style);
qobject_cast<QApplication*>(QApplication::instance())->setStyleSheet(style);
file.close();
}
}
});
timer.start(33);
}
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QWidget win;
win.show();
realRefreshStyle();
return app.exec();
}
下面是优化版本
#include
#include
#include
#include
#define STYLE_SHEET_PATH "style.qss"
#define STYLE_SHEET_CONFIG "style.ini"
void realRefreshTheme(QString &style)
{
QMap<QString, QString> theme;
QSettings settings(STYLE_SHEET_CONFIG);
for(const QString& key : settings.allKeys())
{
const QString &path = settings.value(key).toString();
QFile file(path);
if (file.open(QIODevice::ReadOnly))
{
theme.insert(key, file.readAll());
}
else {
theme.insert(key, "");
}
}
for(const QString& key : theme.keys())
{
style.replace(key, theme[key]);
}
}
void realRefreshStyle()
{
QFile file(STYLE_SHEET_PATH);
if (file.open(QIODevice::ReadOnly))
{
QString style = file.readAll();
realRefreshTheme(style);
qobject_cast<QApplication*>(QApplication::instance())->setStyleSheet(file.readAll());
file.close();
}
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget w;
w.show();
#ifdef QT_DEBUG
QFileSystemWatcher fileWatcher;
fileWatcher.addPath(STYLE_SHEET_PATH);
fileWatcher.addPath(STYLE_SHEET_CONFIG);
QObject::connect(&fileWatcher, &QFileSystemWatcher::fileChanged, [](){
realRefreshStyle();
});
#else
realRefreshStyle();
#endif
return a.exec();
}
关于本人项目需求的解决方法代码如下:
//m_styleQssFile代表分QSS1,分QSS2的路径
void widget::slot_choose_qss()
{
QFile file(":/Resources/universal.qss");
if (file.open(QIODevice::ReadOnly))
{
QString lVarStyle;
QFile f(m_styleQssFile);
if (f.open(QIODevice::ReadOnly))
{
lVarStyle = f.readAll();
}
else {
}
QString style = file.readAll();
style = style.replace(QString("$myStyle"), lVarStyle);
file.close();
qobject_cast<QApplication*>(QApplication::instance())->setStyleSheet(style);
}
}