c++ - 如何更新样式表的单个属性?
问题描述
我有一个窗口:
class MyWindow : public QWindow
{
.....
};
MyWindow *window;
和一组样式表属性:
MyWindow
{
style1: value1;
style2: value2;
}
为了在窗口上设置这些属性,我必须调用:
window->setStyleSheet( "style1: value1" );
window->setStyleSheet( "style2: value2" );
例如设置 a 的对齐方式QPushButton
需要设置text-align
属性。
现在假设我要修改 style1 的 value1 值。我可以通过两种方式做到这一点:
window->setStyleSheet( "style1: new-value" );
或者
window->setStyleSheet( "style1: new-value; style2: value2" );
不同之处在于,对于第二种情况,我需要重建之前设置的整个样式表并附加我的更改。
现在的问题 -据你所知,是否有任何窗口/样式集我绝对必须按照 #2 的方式进行操作?
当然,为了更改 1 个属性值而必须重建属性表会很奇怪,但我想问一下以防万一。
解决方案
Background
In order to set those properties on the window I have to call:
window->setStyleSheet( "style1: value1" ); window->setStyleSheet( "style2: value2" );
The stylesheets are cascading
, but not cumulative, meaning that the later stylesheet will cancel the previous one.
Consider this example:
auto *label = new QLabel("test", this);
label->setStyleSheet("background-color: yellow");
label->setStyleSheet("color: red");
The result is: the text is red, but the background has the default color.
If the last two rows switch places, the result is: the background is yellow, but the text has now the default color.
So, the answer to your question about when you absolutely have to do the way #2 is:
always
Solution
Having this background in mind, in order to answer the question from the title, I would suggest you the following solution:
- Convert the stylesheet to a JSON
- Update the value of choice
- Convert the JSON back to a stylesheet
- Set the new stylesheet to the widget
Example
The proposed solution might sound complicated, but fortunately I have prepared a class StylesheetManipulator
, which has the neccessary functionality, as well as an example of how to use it:
StylesheetManipulator.h
#ifndef STYLESHEETMANIPULATOR_H
#define STYLESHEETMANIPULATOR_H
#include <qglobal.h>
#include <QJsonArray>
class StylesheetManipulator
{
public:
static QString updateStylesheetProperty(const QString &styleSheet, const QString &selector, const QString &property, const QString &newValue);
private:
static QJsonArray styleSheetToJson(const QString &styleSheet);
static QJsonArray styleSheetPropertiesToJson(const QString &properties);
static QJsonArray updateValue(const QString &selector, const QString &propertyName, const QString &newValue, const QJsonArray &jsonStyleSheet);
static QString jsonToStyleSheet(const QJsonArray &jsonStyleSheet);
};
#endif // STYLESHEETMANIPULATOR_H
StylesheetManipulator.cpp
QString StylesheetManipulator::updateStylesheetProperty(const QString &styleSheet, const QString &selector, const QString &property, const QString &newValue)
{
return jsonToStyleSheet(updateValue(selector, property, newValue, styleSheetToJson(styleSheet)));
}
QJsonArray StylesheetManipulator::styleSheetToJson(const QString &styleSheet)
{
QJsonArray jsonStyleSheet;
if (styleSheet.isEmpty())
return jsonStyleSheet;
foreach (const QString &style, styleSheet.trimmed().split("}")) {
const QString &trimmedStyle(style.trimmed());
if (!trimmedStyle.isEmpty()) {
const QStringList &list(trimmedStyle.split("{"));
jsonStyleSheet.append(QJsonObject {
{"selector", list.first().trimmed()},
{"properties", styleSheetPropertiesToJson(list.last())}
});
}
}
return jsonStyleSheet;
}
QJsonArray StylesheetManipulator::styleSheetPropertiesToJson(const QString &properties)
{
QJsonArray jsonProperties;
if (properties.isEmpty())
return jsonProperties;
foreach (const QString &property, properties.trimmed().split(";")) {
const QString &trimmedProperty(property.trimmed());
if (!trimmedProperty.isEmpty()) {
const QStringList &list(trimmedProperty.split(":"));
jsonProperties.append(QJsonObject{
{"name", list.first().trimmed()},
{"value", list.last().trimmed()}
});
}
}
return jsonProperties;
}
QJsonArray StylesheetManipulator::updateValue(const QString &selector, const QString &propertyName, const QString &newValue, const QJsonArray &jsonStyleSheet)
{
QJsonArray a;
foreach (const QJsonValue &value, jsonStyleSheet) {
const QJsonObject ¤tStyle(value.toObject());
const QString ¤tSelector(currentStyle["selector"].toString());
bool selectorFound = currentSelector == selector;
QJsonArray properties;
foreach (const QJsonValue &value, currentStyle["properties"].toArray()) {
QJsonObject property(value.toObject());
if (selectorFound && (property["name"].toString() == propertyName))
property["value"] = newValue;
properties.append(property);
}
a.append(QJsonObject{
{"selector", currentSelector},
{"properties", properties}
});
}
return a;
}
QString StylesheetManipulator::jsonToStyleSheet(const QJsonArray &jsonStyleSheet)
{
QString styleSheet;
foreach (const QJsonValue &value, jsonStyleSheet) {
const QJsonObject ¤tStyle(value.toObject());
styleSheet.append(currentStyle["selector"].toString() + " {");
foreach (const QJsonValue &value, currentStyle["properties"].toArray()) {
QJsonObject property(value.toObject());
styleSheet.append(" " + property["name"].toString() + ": " + property["value"].toString() + ";");
}
styleSheet.append(" } ");
}
return styleSheet;
}
MainWindow.cpp
MainWindow::MainWindow(QWidget *parent) :
QWidget(parent)
{
auto *label = new QLabel("test", this);
auto *l = new QVBoxLayout(this);
label->setStyleSheet("QFrame { background-color: yellow; border: 2px solid blue } QLabel { color: red; }");
label->setStyleSheet(StylesheetManipulator::updateStylesheetProperty(label->styleSheet(), "QLabel", "color", "green"));
l->addWidget(label);
resize(300, 200);
}
The complete code of the example is available on GitHub
The example produces the following result:
Please note, that although initially the text color was set to red (QLabel { color: red; }
), it has been effectively changed to green.
推荐阅读
- arduino - Arduino Uno 上传失败
- if-statement - 为什么我的 if 和 else if 语句没有运行?
- r - R 有 Wayland 后端吗?
- spring-kafka - 带有 DataSourceTransactionManager + KafkaTransactionManager 的 ChainedTransactionManager。Kafka 发送操作没有回滚
- python - 如何为 django 模型字段生成选择元组以在表单中使用
- r - 根据ggplot中的条件着色点
- javascript - 克隆并更改内部按钮的onclick代码
- c++ - 从辅助监视器捕获图像、裁剪和保存
- java - 如何在列表视图中在我的应用程序上显示来自 sqlite 数据库的记录
- sql - 如何在 oracle XMLTYPE XMLTABLE 中支持 1 级路径目录