Qt实现通过.css样式文件实时加载QSS样式

news2024/11/26 21:52:38

初学Qt时要想通过QSS修改控件QWidget,QPushButton等原生基础控件的样式,一般都是直接在.ui文件中直接添加qss,或者在代码中通过setStyleSheet(QString qss)来设置。当程序很大时,很多地方需要复用样式时会非常麻烦,qss写的到处都是,极难维护(如下图所示两种常见初学方式)。

为了更好地管理样式,提高复用率,应该把QSS样式写在一个个文件中(文件后缀是.css或者.qss都可以,但是建议.css好点,因为Notepad++可以进行语法识别高亮提醒),程序初始化时统一加载到主程序中,这样所有控件都会自动继承,且通过属性过滤器决定哪个控件生效(如下图)。

这样通过读取 “StyleList.txt” 文件可知有多少个css文件可以加载,读取所有文件内容拼接成一个超长QString再使用setStyleSheet(QString qss)来加载。期间也可以监控这些文件的内容变化,一旦有内容更新马上重新加载。

举例,我一个测试程序的exe文件在bin目录下,bin同级目录下有res/QSS来存放QSS样式相关文件

创建一个类 “QssLoadTool” 用于加载,监控这些文件:

qssloadtool.h

#ifndef QSSLOADTOOL_H
#define QSSLOADTOOL_H

#include <QObject>
#include <QFile>
#include <QFileSystemWatcher>


class QssLoadTool : public QObject
{
    Q_OBJECT
public:
    explicit QssLoadTool(QObject *parent = nullptr);

    // 设置qss样式文件的根文件(根文件记录了需要加载的所有qss样式文件名)
    static void setQssFileListRootFile(const QString &QssRootFile);
    static QString getQssFileListRootFile();

    // 加载所有qss文件刷新程序控件样式
    static void LoadQss2RefreshStyle();

    // 监控qss相关文件,发送修改就重新加载(在main调用一次即可)
    static void WatchQSSFileChange(QFileSystemWatcher *FileWatcher);

private :

    // 本程序所需qss样式文件的根文件
    static QString m_QssRootFile;

    // 程序运行位置
    static QString m_currentPath;
};


#endif // QSSLOADTOOL_H

qssloadtool.cpp

#include "qssloadtool.h"
#include <QDebug>
#include <QApplication>

QString QssLoadTool::m_QssRootFile = "";

QssLoadTool::QssLoadTool(QObject *parent) : QObject(parent)
{
    // 获取应用程序当前路径
    m_currentPath = QCoreApplication::applicationDirPath();
}

void QssLoadTool::setQssFileListRootFile(const QString &QssRootFile)
{
    m_QssRootFile = QssRootFile;
}

QString QssLoadTool::getQssFileListRootFile()
{
    return m_QssRootFile;
}

void QssLoadTool::LoadQss2RefreshStyle()
{
    if(m_QssRootFile.isEmpty())
    {
        qDebug() << "未设置qss样式文件的根文件:" << m_QssRootFile;
        return;
    }

    qDebug() << __FUNCTION__ << "qss样式发送变更,正在重新加载...";

    QFile file(m_QssRootFile);
    if (file.open(QIODevice::ReadOnly))
    {

       QString style = file.readAll();
       file.close();

       QStringList styleList = style.split("\n");
       style.clear();
       QString path = "";
       for(const QString &qssfile : styleList)
       {
           path = m_currentPath + "/../res/QSS/" + qssfile;

           file.setFileName(path.trimmed());
           if(file.open(QIODevice::ReadOnly))
           {
               style = style + file.readAll().trimmed();
               file.close();
           }
           else
           {
               qDebug() << "打开文件失败! ---> " << path;
           }
       }

       qobject_cast<QApplication*>(QApplication::instance())->setStyleSheet(style);

    }
}

void QssLoadTool::WatchQSSFileChange(QFileSystemWatcher *FileWatcher)
{
    if(m_QssRootFile.isEmpty())
    {
        qDebug() << "未设置qss样式文件的根文件:" << m_QssRootFile;
        return;
    }

    FileWatcher->addPath(m_QssRootFile);

    qDebug() << "监控qss样式文件的根文件:" << m_QssRootFile;

    QFile file(m_QssRootFile);
    if (file.open(QIODevice::ReadOnly))
    {
       QString files = file.readAll();
       file.close();
       QStringList fileList = files.split("\n");
       QString path = "";
       for(const QString &qssfile : fileList)
       {
           path = m_currentPath + "/../res/QSS/" + qssfile;
           FileWatcher->addPath(path.trimmed());

           qDebug() <<"监控qss样式文件 :" << path.trimmed();
       }
    }

    // 被监控的qss文件发生修改时,马上重新加载所有qss样式文件
    QObject::connect(FileWatcher, &QFileSystemWatcher::fileChanged, [](){
        QssLoadTool::LoadQss2RefreshStyle();
    });
}

main.cpp中使用方式:

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
        
    // exe所在位置
    QString currentPath = QCoreApplication::applicationDirPath();
    
    // 读取所有的qss样式加载到程序中
    QssLoadTool::setQssFileListRootFile(currentPath + "/../res/QSS/StyleList.txt");
    QssLoadTool::LoadQss2RefreshStyle();
    
    // 监控所有样式文件的内容变化(也可以不监控,即接下来的这两句代码不写)
    QFileSystemWatcher fileWatcher;
    QssLoadTool::WatchQSSFileChange(&fileWatcher);

    // 主界面启动
    ProjectMainWindow w;
    w.show();

    return a.exec();
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1561052.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++教学——从入门到精通 6.ASCII码与字符型

如何把小写字母转换成大写字母呢&#xff1f; 这个问题问的好&#xff0c;首先我们要新学一个类型——char 这个类型就是字符型 再来说说ASCII码 给大家举几个例子 空格————32 0————48 9————57 A————65 Z————90 a————97 z————122 我们…

LeetCode-560. 和为 K 的子数组【数组 哈希表 前缀和】

LeetCode-560. 和为 K 的子数组【数组 哈希表 前缀和】 题目描述&#xff1a;解题思路一&#xff1a;一边算前缀和一边统计。这里用哈希表统计前缀和出现的次数&#xff0c;那么和为k的子数组的个数就是当前前缀和-k的个数&#xff0c;即preSums[presum - k]。画个图表述就是&a…

NGINX 反向代理 CORS

我遇到了一个问题就是 Nginx 是作为反向代理服务器部署的&#xff0c;但因为 Nginx 的配置导致 CORS 问题。 在这个时候我们可以对 Nginx 的配置文件进行修改&#xff1a; 在 location 后添加下面的内容&#xff1a; add_header Access-Control-Allow-Origin *; add_header A…

Kafka入门到实战-第二弹

Kafka入门到实战 Kafka快速开始官网地址Kafka概述Kafka术语Kafka初体验更新计划 Kafka快速开始 官网地址 声明: 由于操作系统, 版本更新等原因, 文章所列内容不一定100%复现, 还要以官方信息为准 https://kafka.apache.org/Kafka概述 Apache Kafka 是一个开源的分布式事件流…

ES6学习之路:迭代器Iterator和生成器Generator

迭代器 一、知识背景 什么是迭代器 迭代器就是在一个数据集合中不断取出数据的过程迭代和遍历的区别 遍历是把所有数据都取出迭代器注重的是依次取出数据&#xff0c;它不会在意有多少数据&#xff0c;也不会保证能够取出多少或者能够把数据都取完。比如斐波那契额数列&#…

离散时间动态系统的集成自适应动态规划智能控制-北科大博毕

主要内容&#xff1a; 传统值迭代产生迭代控制策略&#xff0c;给出稳定性和吸引域判据&#xff1b;传统值迭代则迭代过程中得到可容许策略折扣因子对迭代控制策略可容许的影响&#xff0c;神经网络对未知系统建模&#xff0c;讨论模型网络权重更新情况下参数误差和系统状态估…

TikTok零播放?可能是海外代理IP的问题

在当今社交媒体的蓬勃发展中&#xff0c;TIKTOK作为一款备受欢迎的短视频平台&#xff0c;其直播功能也逐渐受到用户的青睐。然而&#xff0c;有时候跨境电商商家在进行直播时却面临着一个令人头疼的问题&#xff1a;没有观众。这时候&#xff0c;海外代理IP可能是一个潜在的原…

吴恩达:别光盯着GPT-5,用GPT-4做个智能体可能提前达到GPT-5的效果

最近&#xff0c;斯坦福大学教授吴恩达在演讲中提到&#xff0c;他们发现&#xff0c;基于 GPT-3.5 构建的智能体工作流在应用中表现比 GPT-4 要好。 AI 智能体是去年很火的一个话题&#xff0c;但是 AI 智能体到底有多大的潜力&#xff0c;很多人可能没有概念。 最近&#x…

【环境搭建】(四)ubuntu22.04系统安装Opencv4.8.0+Opencv-contrib4.8.0

一个愿意伫立在巨人肩膀上的农民...... 一、安装下载所需工具 1.打开终端&#xff0c;输入以下命令来更新软件源&#xff1a; sudo apt-get update 2.安装wget&#xff1a; sudo apt-get install wget 3.下载opencv和opencv-contrib包&#xff1a; wget -O opencv-4.8.0.…

ISP-VPN实验

文章目录 ISP-VPN实验一&#xff0c;实验拓扑二、实验要求三、IP规划四、实验配置1、IP配置R1的配置R2的配置R3的配置R4的配置R5的配置 2、配置缺省路由3、认证与被认证配置4、HDLC封装5、构建MGRE和GRE6、整个私有网络基于RIP全网可达7、查看路由配置和PC端配置8、PC端pingR5的…

Vue element-plus 导航栏 [el-menu]

导航栏 [el-menu] Menu 菜单 | Element Plus el-menu有很多属性和子标签&#xff0c;为网站提供导航功能的菜单。 常用标签&#xff1a; 它里面有两个子标签。el-menu-item&#xff0c;它其实就是el-menu每一个里面的item&#xff0c;item就是真实匹配到路由的每个栏目&#…

【Python使用】嘿马头条完整开发md笔记第3篇:数据库,1 新增【附代码文档】

嘿马头条项目从到完整开发笔记总结完整教程&#xff08;附代码资料&#xff09;主要内容讲述&#xff1a;课程简介&#xff0c;ToutiaoWeb虚拟机使用说明1 产品介绍,2 原型图与UI图,3 技术架构,4 开发,1 需求,2 注意事项。数据库&#xff0c;理解ORM1 简介,2 安装,3 数据库连接…

使用CRXjs、Vite、Vue 开发 Chrome 多页面插件,手动配置 vite.config.ts 和 manifest.json 文件

一、使用CRXjs、Vite、Vue 开发 Chrome 多页面插件&#xff0c;手动配置 vite.config.ts 和 manifest.json 文件 一、创建 Vue 项目 1. 使用 Vite 创建 Vue 项目 npm create vitelatest # npm yarn create vite # yarn pnpm create vite # pnpm选择 Vue 和 TS 进入项目…

SpringBoot微服务实现深度学习:构建AGI道路的基石+实战案例演示

&#x1f389;&#x1f389;欢迎光临&#xff0c;终于等到你啦&#x1f389;&#x1f389; &#x1f3c5;我是苏泽&#xff0c;一位对技术充满热情的探索者和分享者。&#x1f680;&#x1f680; &#x1f31f;持续更新的专栏《Spring 狂野之旅&#xff1a;从入门到入魔》 &a…

4月4日生效!管控升级!继续围堵 | 百能云芯

据路透社29日报道&#xff0c;美国拜登政府当天修改规则&#xff0c;升级针对中国人工智能&#xff08;AI&#xff09;芯片和相关工具出口管制的措施。报道声称&#xff0c;这是美国以国家安全为由阻碍中国芯片制造业发展的努力的一部分。 美国商务部下属的工业与安全局&#x…

移动硬盘损坏打不开?别慌,数据恢复有妙招!

移动硬盘作为我们日常存储和传输数据的重要工具&#xff0c;一旦遇到损坏打不开的情况&#xff0c;无疑会让我们倍感焦虑。毕竟&#xff0c;其中存储的文件可能关乎工作、学习或生活的方方面面&#xff0c;一旦丢失&#xff0c;后果不堪设想。那么&#xff0c;当移动硬盘损坏打…

UE5 SQLite笔记

开发环境&#xff1a; 系统&#xff1a;Windows 10 64 bit 引擎&#xff1a;Unreal Engine 5.1.1 IDE&#xff1a;JetBrains Rider 2023.2.1 语言&#xff1a;C 工具&#xff1a;DB Browser for SQLite SQLite数据类型&#xff1a; //INTEGER TEXT BLOB REAL NUMERIC/*integer…

使用Pilotfish扩展Sui执行能力

Pilotfish第一个多机智能合约执行引擎&#xff0c;使Sui网络的验证节点可以利用多台机器&#xff0c;并在负载增加时自动扩展以执行更多的交易。这一目标实现不会影响可靠性或功能完整性。 Pilotfish可以从内部执行机器的故障中恢复&#xff0c;并支持Sui的全面动态操作。其流…

TCP粘包是怎么回事,如何处理?

还是大剑师兰特&#xff1a;曾是美国某知名大学计算机专业研究生&#xff0c;现为航空航海领域高级前端工程师&#xff1b;CSDN知名博主&#xff0c;GIS领域优质创作者&#xff0c;深耕openlayers、leaflet、mapbox、cesium&#xff0c;canvas&#xff0c;webgl&#xff0c;ech…

Wafer的T7 Code是什么,怎么来的

1、T7 Code是什么 在半导体Cim系统中,waferstart 业务需要支持 Sorter 读取 Wafer 的 T7 Code,与 MES 的 Wafer ID 进行绑定,以便向 前追溯 Wafer 历史,那么问题来了,T7code 是什么 Wafer的T7 Code是一种背面刻号,用于标识双面抛光的晶圆。这种标记采用二维矩阵代码符号,…