0

I have an array of colours of size n. In my program, the number of teams is always <= n, and I need to assign each team a unique color. This is my color array:

private static Color[] TEAM_COLORS = {Color.BLUE, Color.RED, Color.CYAN, Color.GREEN, Color.ORANGE, Color.PINK};

When I print information about the players in the console, I want to print what color is associated with them. When I print the color, I get

java.awt.Color[r=...,g=...,b=...]. 

I understand that this is how Java prints colours. I was wondering if there was a way to instead print BLUE, RED, etc. (so the pre-defined color string).

Daniel Kats
  • 5,141
  • 15
  • 65
  • 102
  • 1
    If `RED` is 255,0,0, what is the name for 254,0,0? Do you expect 16,777,216 color names? – Andrew Thompson Feb 10 '12 at 06:55
  • 1
    possible duplicate of [Java color code convert to color name](http://stackoverflow.com/questions/4126029/java-color-code-convert-to-color-name) – Andrew Thompson Feb 10 '12 at 06:58
  • Those static fields you're using from the `Color` class are there for convenience and reference `Color` objects which do not have any sort of textual names; they are RGB values. – Brian Roach Feb 10 '12 at 06:59
  • I take that back, looking more closely at the post makes me realize the OP was talking about the pre-defined colors, and a limited number of them. – Andrew Thompson Feb 10 '12 at 07:00
  • @AndrewThompson - Yeah but it doesn't change anything, there's no matching `String`s for them in the `Color` class. You have to do the mapping yourself. – Brian Roach Feb 10 '12 at 07:02

7 Answers7

3

Here's a Reflection-based approach:

public static String getColorName(Color c) {
    for (Field f : Color.class.getFields()) {
        try {
            if (f.getType() == Color.class && f.get(null).equals(c)) {
                return f.getName();
            }
        } catch (java.lang.IllegalAccessException e) {
            // it should never get to here
        } 
    }
    return "unknown";
}

Examples:

getColorName(Color.BLACK); // black
getColorName(Color.BLUE); // blue
getColorName(new Color(0,1,2)); // unknown

Demo: http://ideone.com/6cIBD


This will only work with colors defined as fields in java.awt.Color, namely: white, light gray, gray, dark gray, black, red, pink, orange, yellow, green, magenta, cyan and blue.

quantumSoup
  • 27,197
  • 9
  • 43
  • 57
3

One option would be to create a NamedColor enum:

public enum NamedColor {
    BLUE(Color.BLUE),
    RED(Color.RED),
    ...;

    private final Color awtColor;

    private NamedColor(Color awtColor) {
        this.awtColor = awtColor;
    }

    public Color getAwtColor() {
        return awtColor;
    }
}

You'd then make your TEAM_COLORS array an array of NamedColor values instead of Color values, and fetch the AWT color when you need it. The default toString implementation of an enum is its name.

Another alternative would be to create your own Map<Color, String> and consult that when you need the string representation for a color.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • @Jon_Skeet I just extend your reply a bit by adding `colorName` also as an attribute to the enum...that way everything is in one place. – havexz Feb 10 '12 at 07:10
  • @havexz: You *could* do that - but I'd normally just use the enum name unless I had any good reason not to. – Jon Skeet Feb 10 '12 at 12:03
  • @JonSkeet I totally agree with you. Extended code works in situations where all string literals are not external to code (specifically not worried about multi-linugal). But if we have string literals coming from outside code (based on the language) we can than remove the `colorName` member variable and use the api only which fetches from external source via some helper class. But true all these soln has to be thought of according to situation before choosing. – havexz Feb 10 '12 at 14:57
3

Extending @Jon_Skeet reply by adding name also to the enum.

public enum NamedColor {
  BLUE(Color.BLUE, "Blue"),
  RED(Color.RED, "Red"),
  ...;

  private final Color awtColor;
  private final String colorName;

  private NamedColor(Color awtColor, String name) {
    this.awtColor = awtColor;
    this.colorName = name;
  }

  public Color getAwtColor() {
    return awtColor;
  }

  public String getColorName() {
    return colorName;
  }
}

NOTE: IF voting this pls vote @Jon_Skeet reply too as it is extension of that...

Community
  • 1
  • 1
havexz
  • 9,550
  • 2
  • 33
  • 29
1

You might create a class that stores both a String representing the color name, as well as the Color itself.

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
1

If you want your NamedColor to be used as a java.awt.Color and you don't have many colors you can extend it and store the name.

public class NamedColor extends java.awt.Color {

    private String name;

    public NamedColor(String name, java.awt.Color c) {
        super(c.getRGB());
        this.name = name;
    }

    public String toString() {
        return name;
    }
}
ughzan
  • 1,548
  • 1
  • 14
  • 24
0
  public static String colorToString(Color c) {
    if (c == null)  return "NullColor";
    for (var f : Color.class.getFields()) {
      if (f.getType() != Color.class)  continue;
      try {
        if (c.equals(f.get(null)))  return f.getName().toLowerCase();
      } catch (java.lang.IllegalAccessException e) {
        // Ignore. https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/reflect/Field.html#get(java.lang.Object)
      }
    }
    return c.toString();
  }
silvalli
  • 295
  • 2
  • 13
-2

You can try using String.valueOf(color.getRGB())

Rocky
  • 941
  • 7
  • 11