我在QML中有一个颜色对象,我认为它是QColor的一个实例,使用调试器我可以看到颜色对象包含:
a 1
b 0
g 0
hslHue -1
hslLightness 0
hslSaturation 0
hsvHue -1
hsvSaturation 0
hsvValue 0
r 0是否有办法将其转换为人类可读的字符串,例如Red?
发布于 2020-03-19 07:45:42
颜色是一个很难的话题。(如果您曾经将两个屏幕连接到您的计算机,并试图将它们配置为相同的颜色配置文件,您就知道我的意思了。)
不过,我相信“行动纲领”的用意是合理的。如果Qt可以处理人类可读的颜色名称,为什么这不应该是可逆的?
一开始,我看了一下手册- QColor
可以通过向setNamedColor()函数传递RGB字符串(如"#112233")、ARGB字符串(如"#ff112233")或颜色名称(如“蓝色”)来设置颜色。颜色名称取自SVG1.0颜色名称。姓名()函数以"#RRGGBB“格式返回颜色的名称。
关于QColor::name()的声明听起来与OP描述的一模一样。为了完全说服自己,我做了一个MCVE,但是它没有改变任何事情。
好的。所以,这不是一个bug -它是一个特性。
如果它在Qt中缺失了,那么如何添加呢?Qt似乎“知道”所有的名字。因此,如果不能以某种方式利用这一点,那就太烦人了。
我按了一下医生的声音。在医生身上找到的。QColor::setNamedColor的一个链接,用于SVG颜色名称表。
所以,我考虑了一下,只是想复制一下。
我还找到了SVG颜色。请注意,这是用
自: 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似乎既没有提供更少的(在std::map中允许使用作为键),也没有提供std::hash的专门化(在std::unordered_map中允许将使用作为键)。所以,我不得不自己为std::hash做QColor的专攻。
发布于 2020-03-18 11:40:04
但是,我向CPP添加了一个例程,以便使用.name()方法将对象转换回一个字符串,但它返回了RGB值的十六进制符号。
QString myClass::colourName(QColor colr) {
QString hex = colr.name().toLower();
if ( hex.compare("#ff0000") == 0 ) {
return "Red";
} else if ( hex.compare("#00ff00") == 0 ) {
return "Green";
} else if ( hex.compare("#0000ff") == 0 ) {
return "Blue";
}
return hex;
}我的需求很简单,我只需要红色,绿色和蓝色。
发布于 2020-03-19 14:07:53
这并不像听起来那么容易,因为人类总是在某种背景下看到颜色。所以,如果你想得到一个问题的答案“一个人会如何命名颜色”,这将是很难的。上下文不能与这种分类分开。即使是我们可能称之为“无背景”的东西,例如在漆黑房间的深黑色背景上均匀照明的颜色样本卡,也是一种背景--事实上,这种“孤立”的颜色呈现可能是一种不太可能的背景,虽然它有助于提供可再现的结果(在人类完全同意颜色名称的范围内),但并不能很好地与颜色命名的常见场景保持一致--就像你所能想象的那样“奇怪”。我们不会在实验室里命名颜色,而不是正常的。所以我想也许这不是你想要的。
但是看起来,您可能不太关心这个问题,而是只想在字符串和RGB三元组之间进行映射。您可以进行稀疏映射:使用颜色名称列表(例如这一个 ),并使用QMap或QHash之类的稀疏键索引容器进行最简单的32位RGBA到string查找。从QColor::rgba()那里拿钥匙。这样,大多数颜色都不会有指定的名称,但是您所执行的命名的语义非常简单:它要么是来自“可管理”列表的确切的RGB三元组,要么不是。
或者,您可以选择一些任意的“这个足够接近”的度量,并为一堆“附近”颜色指定相同的名称。这完全是武断的,因为在实践中,语境决定了一个人会认为什么是“相同的颜色”。但对某些用途而言,映射的简单性比表示人类视觉感知的映射更为重要。
一旦您选择“聚合”“附近”颜色,您可以使用一些前缀来消除歧义,例如#FF0000可以是red,但是#EE0000可以显示为almost red或closest to red (这取决于距离度量的选择,RGB差值向量的长度是一个可行的度量)。您可以选择基于更有针对性的属性来进行分类,例如,只要饱和度和值超过某个阈值,所有具有相同QColor::hue()的颜色都可能被赋予相同的基本名称(对于任何人来说,#0100001看起来都不太像红色,尽管它是“纯”红色)。这将取决于您需要的名称。如果您想要在"English“字符串和RGB三元组之间进行无损的往返,那么除了获取一个大的颜色列表(例如获得Pantone系统的许可证)并使用它之外,您可以做什么,同时显式地”污染“不符合”几乎“或”喜欢“前缀的颜色。
另一个问题是,RGB三倍本身并不意味着什么。某种校准的颜色空间必须与此相匹配,比如CIE RGB或sRGB。不幸的是,QColor没有携带这些信息。
为了好玩,你可以看看计算颜色命名的参数化模型 :)
https://stackoverflow.com/questions/60738123
复制相似问题