c++ - QColor 到人类可读的字符串
问题描述
我在 QML 中有一个颜色对象,我认为它是 QColor 的一个实例,使用调试器我可以看到颜色对象包含:
a 1
b 0
g 0
hslHue -1
hslLightness 0
hslSaturation 0
hsvHue -1
hsvSaturation 0
hsvValue 0
r 0
有没有办法将它翻译成人类可读的字符串,例如 Red ?
解决方案
颜色是一个很难的话题。(如果您曾经将两个屏幕连接到您的计算机并尝试将它们配置为相同的颜色配置文件,您就会明白我的意思。)
尽管如此,我认为OP的意图是合理的。如果 Qt 可以处理人类可读的颜色名称,为什么不可逆?
起初,我查看了手册 - QColor:
可以通过将 RGB 字符串(例如“#112233”)、ARGB 字符串(例如“#ff112233”)或颜色名称(例如“blue”)传递给setNamedColor()函数来设置颜色。颜色名称取自 SVG 1.0 颜色名称。name()函数以“#RRGGBB”格式返回颜色名称。
关于QColor::name()
听起来的陈述与 OP 所描述的完全一样。为了完全说服自己,我制作了一个 MCVE,但它并没有改变任何东西。
好的。所以,这不是一个错误——它是一个特性。
如果 Qt 中缺少它,如何添加它?Qt 似乎“知道”所有的名字。因此,如果不能以某种方式利用它,那将会很烦人。
我点击了一下文档。并在文档中找到例如。的QColor::setNamedColor SVG 颜色名称表的链接。
所以,我考虑了一秒钟只是为了复制它。
我还找到了SVG Colors。请注意,它带有
自:Qt 5.14
并且仍然是qt5-dev
文档的一部分。(在撰写本文时)。
上woboq.org
,我偶然发现了以下颜色名称的负责源代码qtbase/src/gui/painting/qcolor.cpp
:
#ifndef QT_NO_COLORNAMES
/*
CSS color names = SVG 1.0 color names + transparent (rgba(0,0,0,0))
*/
#ifdef rgb
# undef rgb
#endif
#define rgb(r,g,b) (0xff000000 | (r << 16) | (g << 8) | b)
static const struct RGBData {
const char name[21];
uint value;
} rgbTbl[] = {
{ "aliceblue", rgb(240, 248, 255) },
{ "antiquewhite", rgb(250, 235, 215) },
{ "aqua", rgb( 0, 255, 255) },
…
{ "yellow", rgb(255, 255, 0) },
{ "yellowgreen", rgb(154, 205, 50) }
};
static const int rgbTblSize = sizeof(rgbTbl) / sizeof(RGBData);
#undef rgb
最后,我最终进入了QColor::colorNames():
QStringList QColor::colorNames() [静态]
返回包含 Qt 知道的颜色名称的QStringList 。
另请参见预定义颜色。
使用所有颜色名称的列表(Qt 可以识别)很容易构建反向映射表。
我制作了一个MCVE testQColorName.cc
来证明这一点:
#include <functional>
#include <unordered_map>
// Qt header:
#include <QtWidgets>
namespace std {
template <> struct hash<QColor> {
size_t operator()(const QColor &color) const
{
return std::hash<QRgb>()(color.rgb());
}
};
} // namespace std
typedef std::unordered_map<QColor, QString> ColorNameMap;
class ColorButton: public QPushButton {
private:
QColor _qColor;
public:
explicit ColorButton(
const QString &text = QString(), const QColor &qColor = Qt::black,
QWidget *pQParent = nullptr):
QPushButton(text, pQParent)
{
setColor(qColor);
}
virtual ~ColorButton() = default;
ColorButton(const ColorButton&) = delete;
ColorButton& operator=(const ColorButton&) = delete;
const QColor& color() const { return _qColor; }
void setColor(const QColor &qColor)
{
_qColor = qColor;
QFontMetrics qFontMetrics(font());
const int h = qFontMetrics.height();
QPixmap qPixmap(h, h);
qPixmap.fill(_qColor);
setIcon(qPixmap);
}
QColor chooseColor()
{
setColor(QColorDialog::getColor(_qColor, this, text()));
return _qColor;
}
};
// main application
int main(int argc, char **argv)
{
qDebug() << "Qt Version:" << QT_VERSION_STR;
QApplication app(argc, argv);
// setup data
const ColorNameMap qMapColorNames = []() {
ColorNameMap qMapColorNames;
const QStringList qColorNames = QColor::colorNames();
for (const QString &qColorName : qColorNames) {
qMapColorNames[QColor(qColorName)] = qColorName;
qDebug() << qColorName;
}
return qMapColorNames;
}();
// setup GUI
QWidget qWinMain;
qWinMain.setWindowTitle(QString::fromUtf8("Test Color Name"));
QHBoxLayout qHBox;
QLabel qLblColor(QString::fromUtf8("Color:"));
qHBox.addWidget(&qLblColor);
QLineEdit qEditColor;
qHBox.addWidget(&qEditColor, 1);
ColorButton qBtnColor;
qHBox.addWidget(&qBtnColor);
qWinMain.setLayout(&qHBox);
qWinMain.show();
qEditColor.setText(qBtnColor.color().name());
// install signal handlers
QObject::connect(&qBtnColor, &QPushButton::clicked,
[&]() {
const QColor qColor = qBtnColor.chooseColor();
const ColorNameMap::const_iterator iter = qMapColorNames.find(qColor);
qEditColor.setText(iter != qMapColorNames.end() ? iter->second : qColor.name());
});
QObject::connect(&qEditColor, &QLineEdit::textEdited,
[&](const QString &text) {
const QColor qColor(text);
qBtnColor.setColor(qColor);
});
// runtime loop
return app.exec();
}
输出:
控制台输出:
Qt Version: 5.13.0
"aliceblue"
"antiquewhite"
"aqua"
"aquamarine"
"azure"
"beige"
"bisque"
"black"
"blanchedalmond"
"blue"
"blueviolet"
"brown"
"burlywood"
"cadetblue"
"chartreuse"
"chocolate"
"coral"
"cornflowerblue"
"cornsilk"
"crimson"
"cyan"
"darkblue"
"darkcyan"
"darkgoldenrod"
"darkgray"
"darkgreen"
"darkgrey"
"darkkhaki"
"darkmagenta"
"darkolivegreen"
"darkorange"
"darkorchid"
"darkred"
"darksalmon"
"darkseagreen"
"darkslateblue"
"darkslategray"
"darkslategrey"
"darkturquoise"
"darkviolet"
"deeppink"
"deepskyblue"
"dimgray"
"dimgrey"
"dodgerblue"
"firebrick"
"floralwhite"
"forestgreen"
"fuchsia"
"gainsboro"
"ghostwhite"
"gold"
"goldenrod"
"gray"
"green"
"greenyellow"
"grey"
"honeydew"
"hotpink"
"indianred"
"indigo"
"ivory"
"khaki"
"lavender"
"lavenderblush"
"lawngreen"
"lemonchiffon"
"lightblue"
"lightcoral"
"lightcyan"
"lightgoldenrodyellow"
"lightgray"
"lightgreen"
"lightgrey"
"lightpink"
"lightsalmon"
"lightseagreen"
"lightskyblue"
"lightslategray"
"lightslategrey"
"lightsteelblue"
"lightyellow"
"lime"
"limegreen"
"linen"
"magenta"
"maroon"
"mediumaquamarine"
"mediumblue"
"mediumorchid"
"mediumpurple"
"mediumseagreen"
"mediumslateblue"
"mediumspringgreen"
"mediumturquoise"
"mediumvioletred"
"midnightblue"
"mintcream"
"mistyrose"
"moccasin"
"navajowhite"
"navy"
"oldlace"
"olive"
"olivedrab"
"orange"
"orangered"
"orchid"
"palegoldenrod"
"palegreen"
"paleturquoise"
"palevioletred"
"papayawhip"
"peachpuff"
"peru"
"pink"
"plum"
"powderblue"
"purple"
"red"
"rosybrown"
"royalblue"
"saddlebrown"
"salmon"
"sandybrown"
"seagreen"
"seashell"
"sienna"
"silver"
"skyblue"
"slateblue"
"slategray"
"slategrey"
"snow"
"springgreen"
"steelblue"
"tan"
"teal"
"thistle"
"tomato"
"transparent"
"turquoise"
"violet"
"wheat"
"white"
"whitesmoke"
"yellow"
"yellowgreen"
笔记:
似乎QColor
它既没有提供 less(允许用作 key in std::map
)也没有提供专门化std::hash
(允许用作 key in std::unordered_map
)。std::hash
所以,我不得不专攻QColor
.
推荐阅读
- mysql - mysqldump 与选择 *
- html - 你如何让一个 div 有一个活跃的或访问的风格?
- ruby - Chef 库问题从 Chef 12 转换为 Chef 14
- javascript - 从显示名称 Discord JS 中获取 id
- sql - SQL Server:如果记录不存在,则将记录插入表中
- security - 从应用程序模拟用户角色(例如经理、承包商等)向 Amazon Elastic Search 发出 POST 请求
- python - 从长字符串中提取歌曲名称
- android - 如何在不重新加载导航组件架构的情况下导航到上一个片段
- python - 多线程 python 发布请求
- php - 如何在 PHP 中转换特殊字符