2010-08-04 9 views
5

Aby przedstawić listę obiektów o różnych kolorach w widgecie GWT, musimy uzyskać dynamicznie listę kolorów o tak różnych kolorach jak obiekty. Ponieważ rozmiar Listy może się różnić, musimy być w stanie obliczyć taką Listę kolorów.Jak dynamicznie obliczyć listę kolorów?

Odpowiedz

6

Inna wersja mojego rozwiązania z zakresów:

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; 
} 

Ten jest bardziej wyprzedzeniem, gdyż generuje kolory, które różnią się od siebie jak najwięcej (coś jak @aiiobe zrobił).

Ogólnie dzielimy zakres na 3 podzakresy czerwono-zielone i niebieskie, obliczamy, ile kroków potrzebujemy do iteracji każdego z nich (przez zastosowanie pow (zakres, 1f/3)) i iterujemy je.

Biorąc pod uwagę liczbę 3, wygeneruje ona 0x0000B1, 0x00B100, 0x00B1B1. Dla numeru 10 będzie to: 0x000076, 0x0000EC, 0x007600, 0x007676, 0x0076EC, 0x00EC00, 0x00EC76, 0x00ECEC, 0x760000, 0x760076

+1

Jeśli chcesz pominąć szare kolory - potrzebne będą dodatkowe obliczenia. Będziesz potrzebował czegoś 'if (r == g == b), a następnie kontynuacji' w pętli, a także będziesz musiał zwiększyć 'amount' o' Math.pow (ilość, 1f/3) '(aby utworzyć pomijanie szarych kolorów). – bezmax

+1

lub możesz trzymać się różnych odcieni;) – aioobe

+0

Tak, ale nie jestem dobry z HSV, więc zaproponowałem pierwszą rzecz, która przyszła mi do głowy. – bezmax

5

Coś takiego, jak sądzę. Bez losowości, oblicza tylko, jakie kroki koloru podjąć i dzieli cały zakres kolorów na te kroki. Jeśli ograniczysz dolny limit - usuniesz zbyt ciemne kolory, a ograniczenie górnej granicy usunie zbyt jasne kolory.

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

Proszę również zobaczyć moją inną wersję tego rozwiązania na dole. Generuje znacznie lepsze wyniki niż ten, ale jest nieco bardziej złożony. – bezmax

+0

To nawet nie kompiluje. Nie możesz mieć 'List'' 'int' w java. Prawdopodobnie chcesz zmienić to na 'Integer'. – aioobe

+0

Tak, to był błąd literowy. – bezmax

5

Jeśli dobrze rozumiem twoją sytuację, poszukujesz wielu kolorów, które wyglądają na "tak różne, jak to tylko możliwe"? Chciałbym w tym przypadku zasugerować, że zmienisz wartość barwy (dwa czerwone kolory o nieco innej jasności nie będą wyglądać inaczej), więc otrzymasz coś w rodzaju "tęczowej palety":

Można to osiągnąć za pomocą następujący kod:

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

przykładem wykorzystania z a zrzuty ekranu poniżej:

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 i numCols = 40 daje followi NG dwa screeny:

enter image description hereenter image description here

Jeśli potrzebujesz jak ponad 30 kolorach, można oczywiście zmienić jasność i być może nasycenia, jak również i mieć, na przykład, 10 ciemne kolory, 10 półcieni kolory i 10 jasnych kolorów.

Powiązane problemy