Qt自定义读取qss样式表

Table of Contents

    在Qt中一般情况下我们可以通过qss样式表来配置控件的一些样式,但是一些特殊情况下还是需要使用代码来控制样式,它们的颜色之类的样式属性如果直接写在代码里面会写死掉,后期不容易维护以及为换肤造成麻烦。通常写在ini配置文件里面也是可以的,但是这样要维护qss样式和ini配置两份文件。

    下面是将这些配置以css的样式直接写在qss文件中通过代码来解析出我们需要的属性,同时又支持使用属性名来生效样式:

    widget->setProperty("fmlName","calendar");

    解析类头文件

    class FmlStyle {
    public:
    	static FmlStyle* instance();
    	void init(const QString &styleFileContent);
    	const QString& style(const QString &fmlName);
    	QString attr(const QString &fmlName, const QString &attrName);
    
    private:
    	FmlStyle();
    
    private:
    	QMap<QString, QString> m_fmlStyles;
    };
    

    解析类源文件

    FmlStyle::FmlStyle()
    {
    }
    
    FmlStyle* FmlStyle::instance()
    {
    	static FmlStyle s_inst;
    	return &s_inst;
    }
    
    void FmlStyle::init(const QString &styleFileContent)
    {
    	int pos = 0;
    	QRegExp rx("QWidget\\[fmlName=\"\\w+\"\\]"); // 匹配key,如:QWidget[fmlName="calendar"]
    	while ((pos = rx.indexIn(styleFileContent, pos)) != -1) {
    		QString head = styleFileContent.mid(pos, rx.matchedLength());
    		pos += rx.matchedLength();
    		int start = -1;
    		int end = -1;
    		start = styleFileContent.indexOf("{", pos);
    		if (start >= 0) {
    			end = styleFileContent.indexOf("}", start);
    		}
    		if (end - start > 1) {
    			QString body = styleFileContent.mid(start + 1, end - start - 1);
    			pos += body.length();
    			body = body.trimmed();
    			if (body.size() > 0) {
    				m_fmlStyles[head] = body;
    			}
    		}
    	}
    }
    
    const QString& FmlStyle::style(const QString &fmlName)
    {
    	QString head = QString("QWidget[fmlName=\"%1\"]").arg(fmlName);
    	return m_fmlStyles[head];
    }
    
    QString FmlStyle::attr(const QString &fmlName, const QString &attrName)
    {
    	const QString &body = style(fmlName);
    	QStringList attrList = body.split(";");
    	for (int i = 0, count = attrList.size(); i < count; i++) {
    		QStringList strList = attrList[i].split(":");
    		if (strList.size() == 2) {
    			if (strList[0].trimmed() == attrName) {
    				return strList[1].trimmed();
    			}
    		}
    	}
    	return "";
    }
    

    如下样式在qss文件的任意位置:

    QWidget[fmlName="calendar11"] {
    	background: #111111;
        border: none;
        color:#FFFFFF;
        font-size:12px;
        height:30px;
    }
    

    初始化以及读取样式:

        QFile file(":/style.qss");
        if (!file.exists()) {
            qDebug() << "no skin file!!!";
        }
    
        if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
            QString str = file.readAll();
    		FmlStyle::instance()->init(str);
            qApp->setStyleSheet(str);
            file.close();
        }
    
    	QString xx = FmlStyle::instance()->style("calendar");
    	QString xxx = FmlStyle::instance()->attr("calendar", "font-size");
    	QString xxxx = FmlStyle::instance()->attr("calendar", "background");