美文网首页PyQt
一次使用样式表的探索

一次使用样式表的探索

作者: 223480235e8e | 来源:发表于2019-08-01 22:08 被阅读3次

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

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

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

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

    1 ui文件告诉我的秘密

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

    image image

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

    image

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

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

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

    image

    查看其所属类,这货是属于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文件中,并稍加修改,如下图:

    image image

    5 多文件加载

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

    image

    将每类控件的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,大功告成,让我们编译代码,再重新运行程序

    image

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

    好的,关于样式表的内容就分享到这里了,本节的所有代码小豆君已经上传到qq群文件中,有需要的朋友可以自行下载。关注公众号可加微信群和QQ群。

    欢迎关注微信公众号-小豆君Qt分享

    image

    相关文章

      网友评论

        本文标题:一次使用样式表的探索

        本文链接:https://www.haomeiwen.com/subject/ihjhdctx.html