2010-08-04 20 views
5

Para representar una Lista de Objetos con diferentes colores en un GWT-Widget, necesitamos obtener dinámicamente una Lista de colores con tantos colores diferentes como objetos. Dado que el tamaño de la lista puede variar, debemos poder calcular dicha lista de colores.¿Cómo calcular dinámicamente una lista de colores?

Respuesta

6

Otra versión de mi solución con rangos:

List<int> getUniqueColors(int amount) { 
    final int lowerLimit = 0x10; 
    final int upperLimit = 0xE0;  
    final int colorStep = (upperLimit-lowerLimit)/Math.pow(amount,1f/3); 

    final List<int> colors = new ArrayList<int>(amount); 

    for (int R = lowerLimit;R < upperLimit; R+=colorStep) 
     for (int G = lowerLimit;G < upperLimit; G+=colorStep) 
      for (int B = lowerLimit;B < upperLimit; B+=colorStep) { 
       if (colors.size() >= amount) { //The calculated step is not very precise, so this safeguard is appropriate 
        return colors; 
       } else { 
        int color = (R<<16)+(G<<8)+(B); 
        colors.add(color); 
       }    
      } 
    return colors; 
} 

Este es más antelación, ya que genera los colores que difieren entre sí tanto como sea posible (algo así como lo hizo @aiiobe).

Generalmente dividimos el rango en 3 subrangos de rojo verde y azul, calculamos cuántos pasos necesitamos para iterar cada uno de ellos (aplicando un pow (rango, 1f/3)) y los iteramos.

Dado el número 3, por ejemplo, generará 0x0000B1, 0x00B100, 0x00B1B1. Para el número 10 será: 0x000076, 0x0000EC, 0x007600, 0x007676, 0x0076EC, 0x00EC00, 0x00EC76, 0x00ECEC, 0x760000, 0x760076

+1

Si desea omitir los colores grises, se necesitarán algunos cálculos adicionales. Necesitarías algunos 'if (r == g == b) then continue' en el ciclo y también necesitarías aumentar la' amount' por 'Math.pow (amount, 1f/3)' (para hacer omitiendo los colores grises posibles). – bezmax

+1

o podría seguir variando el tono;) – aioobe

+0

Sí, pero no soy bueno con HSV, así que propuse lo primero que se me ocurrió. – bezmax

5

Algo como esto haría, supongo. Sin aleatoriedad, simplemente calcula qué pasos de color tomar y divide todo el rango de color en esos pasos. Si limita el límite inferior, eliminará los colores demasiado oscuros, y al limitar el límite superior eliminará los colores demasiado brillantes.

List<Integer> getUniqueColors(int amount) { 
    final int lowerLimit = 0x101010; 
    final int upperLimit = 0xE0E0E0; 
    final int colorStep = (upperLimit-lowerLimit)/amount; 

    final List<Integer> colors = new ArrayList<Integer>(amount); 
    for (int i=0;i<amount;i++) { 
     int color = lowerLimit+colorStep*i; 
     colors.add(color); 
    } 
    return colors; 
} 
+0

También vea mi otra versión de esta solución en la parte inferior. Genera resultados mucho mejores que este, pero es un poco más complejo. – bezmax

+0

Eso ni siquiera compila. No puede tener una 'Lista' de' int' en java. Probablemente quieras cambiar eso a 'Entero '. – aioobe

+0

Sí, fue un error tipográfico. – bezmax

5

Si entiendo su situación correcta, lo que busca es un número de colores que se ven especie de "lo más diferente posible"? En ese caso, le sugiero que modifique el valor del tono (dos colores rojos con brillo ligeramente diferente no se verán muy diferentes), por lo que obtendrá algo parecido a una "paleta de arco iris":

Esto se puede lograr con código siguiente:

Color[] cols = new Color[n]; 
for (int i = 0; i < n; i++) 
    cols[i] = Color.getHSBColor((float) i/n, 1, 1); 

un ejemplo de uso con una capturas de pantalla a continuación:

import java.awt.*; 

public class TestComponent extends JPanel { 

    int numCols = 6; 

    public void paint(Graphics g) { 

     float h = 0, dh = (float) getHeight()/numCols; 
     Color[] cols = getDifferentColors(numCols); 

     for (int i = 0; i < numCols; i++) { 
      g.setColor(cols[i]); 
      g.fillRect(0, (int) h, getWidth(), (int) (h += dh)); 
     } 
    } 

    public static Color[] getDifferentColors(int n) { 
     Color[] cols = new Color[n]; 
     for (int i = 0; i < n; i++) 
      cols[i] = Color.getHSBColor((float) i/n, 1, 1); 
     return cols; 
    } 

    public static void main(String s[]) { 
     JFrame f = new JFrame(); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     f.add(new TestComponent()); 
     f.setSize(200, 200); 
     f.setVisible(true); 
    } 
} 

numCols = 6 y numCols = 40 produce el followi ng dos capturas de pantalla:

enter image description hereenter image description here

Si necesita al igual que más de 30 colores, usted podría, por supuesto, cambiar el brillo y quizás la saturación así, y tienen, por ejemplo, 10 colores oscuros, 10 colores de tonos medios y 10 colores brillantes

Cuestiones relacionadas