一.效果
二.原理
上篇 Qt换肤之一:基于QSS 中实现了基于QSS换肤,但是QSS文件通常不会暴露出来,这样的话软件发布后,皮肤颜色也就无法修改了。
这里依然用到了QSS文件,但是只用了一份QSS文件,文件里的颜色值通过XML来配置。
三.实现
XML举例,这个XML很简单,实际使用时会复杂很多。
<?xml version="1.0" encoding="UTF-8"?>
<TopicColor>
<ColorItem key="bordercolor" value="rgba(74,184,161)"></ColorItem>
<ColorItem key="backgroundcolor" value="rgba(74,184,161)"></ColorItem>
<ColorItem key="normalcolor" value="rgba(74,184,161)"></ColorItem>
<ColorItem key="hovercolor" value="rgba(74,184,161,200)"></ColorItem>
<ColorItem key="presscolor" value="rgba(74,184,161)"></ColorItem>
<ColorItem key="QSlider::add-page" value="rgba(74,184,161,50)"></ColorItem>
<ColorItem key="QSlider::sub-page" value="rgba(74,184,161)"></ColorItem>
</TopicColor>
XML解析,更复杂XML文件的解析可参考:Qt之读(解析)XML文件
void testUI::parseXMLFile()
{
QString filePath = QApplication::applicationDirPath() + "/TopicConfig.xml";
QFile file(filePath);
if(!file.open(QIODevice::ReadOnly))
{
qDebug()<<"open topic config file failed";
return;
}
QDomDocument docment;
bool ret = docment.setContent(&file);
if(!ret)
{
qDebug()<<"set content failed";
file.close();
return;
}
file.close();
QDomElement root = docment.documentElement();
QDomNode node = root.firstChild();
while(!node.isNull())
{
if(node.isElement())
{
QDomElement element = node.toElement();
m_colorMap.insert(element.attribute("key"), element.attribute("value"));
}
node = node.nextSibling();
}
}
QSS文件
QWidget#testUI{
border: 1px solid %bordercolor%;
border-radius: 0px;
}
QWidget#titleWidget{
background: %backgroundcolor%;
}
QLabel#iconLabel,QLabel#titleLabel{
border-radius: 0px;
color: rgb(255,255,255);
background-color: transparent;
border-style: none;
}
.QPushButton{
border-style: none;
border: 0px;
color: rgb(255,255,255);
min-height: 20px;
border-radius: 0px;
background: %normalcolor%;
}
.QPushButton:hover{
background: %hovercolor%;
}
.QPushButton:pressed{
background: %presscolor%;
}
QLineEdit {
border: 1px solid %bordercolor%;
border-radius: 5px;
padding: 0 8px;
background: rgb(255,255,255);
selection-background-color: %hovercolor%;
}
QComboBox {
border-radius: 3px;
padding: 1px 10px 1px 5px;
border: 1px solid %bordercolor%;
}
QComboBox::drop-down {
subcontrol-origin: padding;
subcontrol-position: top right;
width: 15px;
border-left-width: 1px;
border-left-style: solid;
border-top-right-radius: 3px;
border-bottom-right-radius: 3px;
border-left-color: %bordercolor%;
}
QComboBox::down-arrow {
image: url(:/icons/array_down.png);
}
/*去掉item的虚线框*/
QComboBox QAbstractItemView {
outline: 0px;
}
QListView::item:selected {
color: rgb(255,255,255);
background: %normalcolor%;
}
QListView::item:hover {
color: rgb(255,255,255);
background: %hovercolor%;
}
QListView::item {
padding: 0px;
margin: 0px;
height:30px;
}
QProgressBar {
border-radius: 5px;
text-align: center;
border: 1px solid %bordercolor%;
}
QProgressBar::chunk {
width: 5px;
margin: 0.5px;
background-color: %normalcolor%
}
QSlider::groove:horizontal,QSlider::add-page:horizontal {
background: %QSlider::add-page%;
height: 8px;
border-radius: 3px;
}
QSlider::sub-page:horizontal {
height: 8px;
border-radius: 3px;
background: %QSlider::sub-page%;
}
QSlider::handle:horizontal {
width: 13px;
margin-top: -3px;
margin-bottom: -3px;
border-radius: 6px;
background: qradialgradient(spread:pad, cx:0.5, cy:0.5, radius:0.5, fx:0.5, fy:0.5,stop:0.6 rgb(255,255,255), stop:0.778409 %normalcolor%);
}
QSlider::handle:horizontal:hover {
background: qradialgradient(spread: pad, cx: 0.5, cy: 0.5, radius: 0.5, fx: 0.5, fy: 0.5, stop: 0.6 lightgray,stop:0.778409 %hovercolor%);
}
根据XML替换QSS中的变量
void testUI::updateQssFile()
{
QFile file(":/qss/topic.qss");
file.open(QFile::ReadOnly);
QByteArray ba = file.readAll();
file.close();
if(m_colorMap.count() > 0)
{
QMap<QString,QString>::iterator iter = m_colorMap.begin();
for(; iter != m_colorMap.end(); ++iter)
{
QString name = "%" + iter.key() + "%";
ba.replace(name, iter.value().toStdString().c_str());
}
qApp->setStyleSheet(ba);
}
}
void testUI::on_blackTopicButton_clicked()
{
changeStyle("black");
styleTitleButtons();
}
void testUI::on_orangeTopicButton_clicked()
{
changeStyle("orange");
styleTitleButtons();
}
void testUI::on_cancelTopicButton_clicked()
{
changeStyle("");
restoreTitleButtons();
}
void testUI::on_loadTopicButton_clicked()
{
parseXMLFile();
updateQssFile();
styleTitleButtons();
}