样式表使用方法小结

简介: 样式表使用方法小结

当今世界,是一个用户体验至上的时代,每个人对软件的整体风格都提出了自己的要求,而这些都迫使开发者们需要定期的更新软件的界面风格,并为不同用户提供个性化的定制服务。


前面两节小豆君分享了有道界面的美化方法,但是美化的方式还存在很多不足,设置样式的代码散落在各个源文件或是ui设计器中,当需要更新界面风格时,就显得格外繁琐。


下面,小豆君就以自己的探索经历,跟大家分享如何有效合理的使用样式表来美化界面。


如果你有更好的方法或建议,欢迎在评论区或群中讨论发言。


1 ui文件告诉我的秘密

在ui设计师界面中对控件属性编辑,信号槽连接等,Qt都会为其生成相应的ui文件(以ui_开头的同名.h文件),所以,当我们编辑控件的样式表时,看看Qt在ui_xxx.h头文件中做了哪些操作。

打开ui_xxx.h文件,浏览该文件中的内容,果然,我们发现了下面的一句话。


原来在ui设计师中编辑的样式表是该pushButton调用了setStyleSheet()接口。

好,那让我们来看看这个接口是怎么声明的。


按下Ctrl键,鼠标移动到setStyleSheet上,该接口高亮,点击接口,直接跳到setStyleSheet的声明处:

查看其所属类,这货是属于QWidget类的,QPushButton间接继承QWidget,而且QWidget类也是所有Qt控件的基类,那么也就是说所有继承自QWidget的类都可以设置样式。

好了,那么我们可以使用setStyleSheet来设置样式了,然而,如果是直接为每个控件调用该接口,和使用ui并无差别,那么,探索继续。


2 文件是个好东西

我们来观察下setStyleSheet的参数,它是一个字符串,那完全可以使用一个文件来将所有的设置语句写在该文件中,对于特殊的控件样式,可以用选择器来设置(关于选择器的内容可查看文章Qt样式表选择器,掌握这些已足够)。


好,我们就以上两节的有道词典为例,首先,将源文件中的所有样式表语句迁移到一个文件中,该文件以qss为后缀名,表明是样式表文件。


3 样式表管理器

毕竟我们使用的是面向对象的程序设计,一切皆为对象,那我们可以专门设计一个类来管理样式表,取名为StyleSheetManager(样式表管理器)。


该管理器需要包含一个数据成员用来存放样式表文件路径。

StyleSheetManager需要对外提供如下接口:

public://1 加载指定的样式表//2 切换指定的样式(换肤)private://1 读取指定文件内容


为此,我们生成实际代码如下:

stylesheetmanager.h

#ifndef STYLESHEETMANAGER_H
#define STYLESHEETMANAGER_H
#include <QObject>
class StyleSheetManager : public QObject
{
    Q_OBJECT
public:
    StyleSheetManager(QObject *parent = 0);
    StyleSheetManager(const QString& filePath, QObject *parent = 0);
    //1 加载指定的样式表字符串
    bool load(const QString& styleStr);
    //1.1加载指定qss文件
    bool loadFile(const QString& path);
    //2 重新加载指定的样式表文件
    bool reload();
    //3 切换指定的样式(换肤)
    bool switchTo(const QString& path);
    //4 qss文件路径存取器
    QString filePath() const;
    void setFilePath(const QString &path);
signals:
    void styleSheetLoaded();
private:
    //1 读取指定文件内容
    QString readFile(const QString& path) const;
    //2 是否为同一文件
    bool isSameFile(const QString &path) const;
private:
    QString m_filePath;//qss文件路径
};
#endif // STYLESHEETMANAGER_H


stylesheetmanager.cpp

#include <QDebug>
#include <QDir>
#include <QFile>
#include <QApplication>
#include "stylesheetmanager.h"
StyleSheetManager::StyleSheetManager(QObject *parent) :
    QObject(parent)
{
}
StyleSheetManager::StyleSheetManager(
    const QString &filePath, QObject *parent
) : QObject(parent)
{
    setFilePath(filePath);
}
bool StyleSheetManager::load(const QString &styleStr)
{
    if (!styleStr.isEmpty() && qApp)
    {
        qApp->setStyleSheet(styleStr);
        setFilePath(styleStr);
        return true;
    }
    return false;
}
bool StyleSheetManager::loadFile(const QString &path)
{
    QString styleStr = readFile(path);
    return load(styleStr);
}
bool StyleSheetManager::reload()
{
    return loadFile(filePath());
}
bool StyleSheetManager::switchTo(const QString &path)
{
    if (isSameFile(path))
    {
        return false;
    }
    return loadFile(path);
}
QString StyleSheetManager::readFile(const QString &path) const
{
    QString ret;
    QFile file(path);
    if (file.open(QIODevice::ReadOnly))
    {
        ret = file.readAll();
        file.close();
    }
    return ret;
}
bool StyleSheetManager::isSameFile(const QString &path) const
{
    return filePath() == path;
}
QString StyleSheetManager::filePath() const
{
    return m_filePath;
}
void StyleSheetManager::setFilePath(const QString &path)
{
    m_filePath = path;
}

4 编写qss文件

将源文件中的样式表代码拷贝到qss文件中,并稍加修改,如下图:

5 多文件加载

细心的同学可能发现,对于比较少的控件,我们一般使用一个文件已经足够了,但是对于复杂多种类的控件,如果全部写在一个文件中,难免会显得过于臃肿,因此我们可以为每一类控件单独创建一个qss文件。

将每类控件的qss代码移到相应的文件中,然后在StyleSheetManager类中添加一个公有接口loadDir()用来加载所有指定目录下的所有qss文件

//1.2加载指定文件夹下的所有qss文件
bool StyleSheetManager::loadDir(const QString &path)
{
    QString styleStr;
    QDir dir(path);
    QFileInfoList fileList = dir.entryInfoList(QDir::Files);
    foreach (const QFileInfo& file, fileList)
    {
        styleStr += readFile(file.absoluteFilePath());
    }
    return load(styleStr);
}


再在main函数最后添加如下两句

StyleSheetManager manager;
manager.loadDir(":/style/");


OK,大功告成,让我们编译代码,再重新运行程序


如果想要实现换肤功能,那就可以建立多个样式表文件夹,调用StyleSheetManager类的换肤接口即可。


更多分享请关注微信公众号:小豆君Qt分享,只要关注,便可加入C++\Qt交流群,一起学习,更可获得所有文章源码。

相关文章
|
8月前
|
人工智能 监控 算法
AI 技能树怎么搭?90%的人第一步就走错了
AI热潮下,别只学工具!真正的竞争力在于构建“AI能力树”:认知层(问题拆解、目标定义)、工程思维(风险评估、方案权衡)、工具协作(高效提问、结果验证)。工具是杠杆,能力才是支点。
|
11月前
|
供应链 JavaScript 安全
B/S云门诊系统源码,java云诊所源码,基于Spring Boot、Vue.js构建
云端SaaS架构云门诊系统,基于Spring Boot+Vue开发,支持医保结算,集成预约挂号、诊疗、收费、库存、会员管理等功能,适用于各类基层医疗机构,可打包为C/S桌面应用,支持外接设备免安装配置。
393 10
|
存储 人工智能 Cloud Native
科研+ AI :深势科技,全新科研范式引领者
深势科技作为AI for Science的引领者,专注于微观粒子行为研究,推动材料科学和生命科学领域的创新。通过AI技术,深势科技加速了药物研发、纳米药物微流控等技术的发展,显著提升了计算性能和实验效率。与阿里云合作,利用其云原生计算和存储服务,深势科技实现了资源弹性调度和高效管理,大幅提升了研发效率,服务于超过50万科研用户,并计划建设AI for Science超级实验室,推动更多科技创新。
902 0
|
前端开发 JavaScript 算法
如何开发人事及OA管理系统的绩效管理板块?(附架构图+流程图+代码参考)
本文深入解析了人事及OA系统中绩效管理模块的设计与实现,涵盖总体架构、功能模块、业务流程、开发技巧、数据库设计、前后端实现及核心算法等。内容详实,配有架构图、流程图和代码示例,适合HR系统开发者与管理者参考,助力构建高效、可扩展的绩效管理体系。
|
人工智能 搜索推荐 测试技术
通义灵码 2.0 智能编码功能评测:Deepseek 加持下的 Python 开发体验
通义灵码 2.0 智能编码功能评测:Deepseek 加持下的 Python 开发体验
890 11
|
数据采集 自然语言处理 开发工具
fasttext实现文本分类
fasttext实现文本分类
1043 0
|
存储 编译器 C语言
【C语言】16 位的值,通过几种不同的方式将其拆分为高 8 位和低 8 位
在实际应用中,通常使用方法 1(位移和位掩码)是最常见的选择,因为它简单、直观,并且不依赖于特定的硬件或编译器特性。方法 3(联合体)适用于需要处理复杂数据结构或需要同时访问多个字段的情况。方法 4(内联函数或宏)适用于需要提高代码重用性和可读性的场景。方法 2(指针和强制类型转换)虽然有效,但不推荐,因为它可能会引入平台依赖性和对齐问题。
1011 2
|
机器学习/深度学习 编解码 负载均衡
MoH:融合混合专家机制的高效多头注意力模型及其在视觉语言任务中的应用
本文提出了一种名为混合头注意力(MoH)的新架构,旨在提高Transformer模型中注意力机制的效率。MoH通过动态注意力头路由机制,使每个token能够自适应选择合适的注意力头,从而在减少激活头数量的同时保持或提升模型性能。实验结果显示,MoH在图像分类、类条件图像生成和大语言模型等多个任务中均表现出色,尤其在减少计算资源消耗方面有显著优势。
770 1
|
安全 网络协议 网络虚拟化
|
机器学习/深度学习 数据采集 算法
特征工程与数据预处理全解析:基础技术和代码示例
在机器学习和数据科学的世界里,数据的质量是建模成功与否的关键所在。这就是特征工程和数据预处理发挥作用的地方。本文总结的这些关键步骤可以显著提高模型的性能,获得更准确的预测,我们将深入研究处理异常值、缺失值、编码、特征缩放和特征提取的各种技术。
709 0

热门文章

最新文章