【问题标题】:How to get the hexadecimal format from color names in Java?如何从 Java 中的颜色名称中获取十六进制格式?
【发布时间】:2019-04-21 00:02:29
【问题描述】:

我有白色、红色、蓝色等颜色名称,我正在尝试获取其对应的十六进制表示。例如,如果我传递 White 之类的参数,它应该返回 #FFFFFF

虽然看起来很简单,但 Java 中没有直接的解决方案。以下是我尝试过的代码。

private String getHexaColor (String basicColor /* White */) {
    java.awt.Color color;
    try {
        java.lang.reflect.Field field = Class.forName("java.awt.Color").getField(basicColor.toLowerCase());
        color = (Color) field.get(null);
    } catch (Exception e) {
        color = null; 
    }

    return (color != null) ? String.format("%06x#", color.getRGB() & 0x00FFFFFF).toUpperCase() : ""; //return #FFFFFF
}

上面的代码运行良好,但我正在寻找一个干净优雅的解决方案,如果至少在最新版本的 Java 中可用的话。

【问题讨论】:

  • 这看起来像是codereview.stackexchange.com的问题
  • 我用谷歌搜索了一些。我能找到的最好的是 S.O.问题的答案就是这样做:stackoverflow.com/questions/2854043/… - 还有一些其他选项涉及第 3 方解决方案。 - 我认为在网上会有一个带有十六进制值的颜色列表,你可以在某个地方抓取和使用。
  • 你的可能颜色名称的范围是什么?
  • 我发现了一个非常详尽的颜色和十六进制值列表。如果是我,我可能会围绕它包装一些代码。 - rapidtables.com/web/color/RGB_Color.html

标签: java java-8


【解决方案1】:

您应该使用格式字符串"#%06X" 而不是"%06x#"。首先,它将# 字符放在您真正想要的位置,其次,它生成一个大写的十六进制字符串,无需在结果上调用toUpperCase()

但是,与显式值映射相比,您的反射操作节省了多少?当我遍历Color 的所有字段时,例如通过

final int constant = Modifier.STATIC | Modifier.FINAL;
Map<String,Integer> m = new HashMap<>();
for(Field f: Color.class.getFields()) try {
    if((f.getModifiers() & constant) == constant && f.getType() == Color.class)
        m.put(f.getName().toLowerCase().replace('_', ' '),
            ((Color)f.get(null)).getRGB() & 0x00FFFFFF);
} catch(ReflectiveOperationException ex) {
    throw new AssertionError(ex);
}
m.forEach((name,rgb) -> System.out.printf("map.put(\"%s\", \"#%06X\");%n", name, rgb));

我明白了

map.put("magenta", "#FF00FF");
map.put("pink", "#FFAFAF");
map.put("green", "#00FF00");
map.put("black", "#000000");
map.put("yellow", "#FFFF00");
map.put("cyan", "#00FFFF");
map.put("dark gray", "#404040");
map.put("red", "#FF0000");
map.put("orange", "#FFC800");
map.put("gray", "#808080");
map.put("white", "#FFFFFF");
map.put("blue", "#0000FF");
map.put("darkgray", "#404040");
map.put("light gray", "#C0C0C0");
map.put("lightgray", "#C0C0C0");

这不是那么大。因此,当我将该输出复制到一个新代码中时,例如

static final Map<String,String> COLOR_CODES;
static {
    Map<String,String> map = new HashMap<>();
    map.put("magenta", "#FF00FF");
    map.put("pink", "#FFAFAF");
    map.put("green", "#00FF00");
    map.put("black", "#000000");
    map.put("yellow", "#FFFF00");
    map.put("cyan", "#00FFFF");
    map.put("dark gray", "#404040");
    map.put("red", "#FF0000");
    map.put("orange", "#FFC800");
    map.put("gray", "#808080");
    map.put("white", "#FFFFFF");
    map.put("blue", "#0000FF");
    map.put("darkgray", "#404040");
    map.put("light gray", "#C0C0C0");
    map.put("lightgray", "#C0C0C0");
    COLOR_CODES = Collections.unmodifiableMap(map);
}
static String getHexaColor(String colorName) {
    return COLOR_CODES.getOrDefault(colorName.toLowerCase(), "");
}

结果很简单,无需反射。维护将独立于生成此版本的反射代码,因为向映射添加新常量比向 java.awt.Color 类添加新常量(重新运行反射代码)更简单。

唯一具有更大灵活性的替代方法是使用properties 文件,它允许在不重新编译应用程序的情况下更新地图。改用上面的代码来生成属性文件很容易,但另一方面,互联网上有足够多的即用型文件具有更多颜色。例如,您可以直接从 w3.org 复制基于 VGA 的网页颜色,而 this extended list 则需要将高级搜索和替换引入属性格式。

【讨论】:

    【解决方案2】:

    使用来自 OpenFX 的 Color,可以为所有 Web 颜色配置一种方法。

    import javafx.scene.paint.Color;
    Color color = Color.web("skyblue");
    

    结果:

    0x87cdebff
    

    这些也作为常量字段存在,因此可以使用自动补全。但我喜欢 CSS/HTML 编辑器中的自动完成功能。


    这是一个独立的依赖库。但是从 java 9 开始,模块化基础设施是可以预期的,而 OpenFX,以前的 JavaFX,是没有问题的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-01-26
      • 2015-04-12
      • 1970-01-01
      • 1970-01-01
      • 2012-07-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多