2013-02-25 12 views
5

Generuję grupę obiektów RectangleF o różnych rozmiarach i położeniach. Jaki byłby najlepszy sposób na wypełnienie ich gradientem Brush w GDI +?Efektywny sposób malowania gradientów prostokąta

W WPF mogę utworzyć LinearGradientBrush, ustawić Start i End relative punktów, a WPF zajmie się resztą.

Jednak w GDI + konstruktor pędzli gradientowych wymaga pozycji we współrzędnych bezwzględnych, co oznacza, że ​​muszę utworzyć pędzel dla każdego prostokąta, co byłoby bardzo skomplikowaną operacją.

Czy brakuje mi czegoś lub w rzeczywistości jest to jedyny sposób?

Odpowiedz

0

polecam Ci stworzyć ogólną metodę tak:

public void Paint_rectangle(object sender, PaintEventArgs e) 
    { 
     RectangleF r = new RectangleF(0, 0, e.ClipRectangle.Width, e.ClipRectangle.Height); 
     if (r.Width > 0 && r.Height > 0) 
     { 
      Color c1 = Color.LightBlue; 
      Color c2 = Color.White; 
      Color c3 = Color.LightBlue; 

      LinearGradientBrush br = new LinearGradientBrush(r, c1, c3, 90, true); 
      ColorBlend cb = new ColorBlend(); 
      cb.Positions = new[] { 0, (float)0.5, 1 }; 
      cb.Colors = new[] { c1, c2, c3 }; 
      br.InterpolationColors = cb; 

      // paint 
      e.Graphics.FillRectangle(br, r); 
     } 
    } 

następnie dla każdego prostokąta zadzwoń:

yourrectangleF.Paint += new PaintEventHandler(Paint_rectangle); 

Jeśli gradrients kolory są takie same, można sprawić, aby metoda krótsza. Nadzieję, że pomógł ..

+1

To nie pomaga przeciwko mojego strachu tworzenia pędzla gradientu dla każdego prostokąta. W rzeczywistości mam 2 pędzle, których potrzebuję do malowania 1000 prostokątów. – Eugen

+0

Przykro mi, kolego, ale myślę, że nie masz innej opcji. Mam problemy z wydajnością, które można poprawić za pomocą wątków. Możesz z tym zaoszczędzić czas. Jak długo zajmuje wypełnienie całego prostokąta przez utworzenie jednego prostokąta liniowego na prostokąt? – Andres

+0

Nie testowałem jeszcze, tylko miałem nadzieję, że proces tworzenia Pędzla jest taki sam jak w WPF i miałem pomysł, że czegoś mi brakuje. Ale wygląda na to, że to jedyny sposób. – Eugen

1

Możesz określić transformację w momencie tuż przed zastosowaniem gradientu, jeśli chcesz zadeklarować pędzel tylko raz. Zauważ, że użycie transformacji zastąpi wiele argumentów konstruktora, które można określić na LinearGradientBrush.

LinearGradientBrush.Transform Property (System.Drawing.Drawing2D)

Aby zmodyfikować transformację wywołać metody na obiekcie szczotki odpowiednie do pożądanych działań na macierzach. Zwróć uwagę, że operacje macierzowe nie są przemienne, więc kolejność jest ważna. Dla swoich celów będziesz prawdopodobnie chciał wykonać je w tej kolejności dla każdego wykonania twoich prostokątów: Skaluj, Obróć, Przesunięcie/Przetłumacz.

LinearGradientBrush.ResetTransform Method @ MSDN

LinearGradientBrush.ScaleTransform Method (Single, Single, MatrixOrder) @ MSDN

LinearGradientBrush.RotateTransform Method (Single, MatrixOrder) @ MSDN

LinearGradientBrush.TranslateTransform Method (Single, Single, MatrixOrder) @ MSDN

Należy pamiętać, że narzędzia do rysowania na poziomie systemu w rzeczywistości nie zawiera definicji zapasów dla pędzla gradientu, więc jeśli masz problemy z wydajnością o tworzeniu wielu pędzli, tworzenie wielu gradientowych pędzli nie powinno kosztować więcej niż narzut GDI +/System.Drawin g utrzymywanie danych wymaganych do zdefiniowania gradientu i stylizacji. Możesz być równie dobry, aby utworzyć pędzel na prostokąt w razie potrzeby, bez konieczności zanurzania się w matematyce wymaganej do dostosowania pędzla za pomocą transformacji.

Brush Functions (Windows) @ MSDN

Oto przykład kodu można sprawdzić w aplikacji WinForms. Ta aplikacja maluje kafelki za pomocą gradientowego pędzla, używając gradientu 45 stopni, skalowanego do największego wymiaru płytki (naiwnie obliczanego). Jeśli będziesz manipulował wartościami i transformacjami, może się okazać, że nie warto używać techniki ustawiającej transformację dla wszystkich twoich prostokątów, jeśli masz nietrywialne definicje gradientów. W przeciwnym razie pamiętaj, że twoje transformacje są stosowane na poziomie światowym, aw świecie GDI oś Y jest odwrócona, podczas gdy w kartezjańskim świecie matematyki jest ona uporządkowana od dołu do góry. Powoduje to również, że kąt zostanie przyłożony zgodnie z ruchem wskazówek zegara, podczas gdy w trygonometrii kąt rośnie w kierunku przeciwnym do ruchu wskazówek zegara, zwiększając wartość dla osi Y skierowanej ku górze.

using System.Drawing.Drawing2D; 

namespace TestMapTransform 
{ 
    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void Form1_Paint(object sender, PaintEventArgs e) 
     { 
      Rectangle rBrush = new Rectangle(0,0,1,1); 
      Color startColor = Color.DarkRed; 
      Color endColor = Color.White; 
      LinearGradientBrush br = new LinearGradientBrush(rBrush, startColor, endColor, LinearGradientMode.Horizontal); 

      int wPartitions = 5; 
      int hPartitions = 5; 

      int w = this.ClientSize.Width; 
      w = w - (w % wPartitions) + wPartitions; 
      int h = this.ClientSize.Height; 
      h = h - (h % hPartitions) + hPartitions; 

      for (int hStep = 0; hStep < hPartitions; hStep++) 
      { 
       int hUnit = h/hPartitions; 
       for (int wStep = 0; wStep < wPartitions; wStep++) 
       { 
        int wUnit = w/wPartitions; 

        Rectangle rTile = new Rectangle(wUnit * wStep, hUnit * hStep, wUnit, hUnit); 

        if (e.ClipRectangle.IntersectsWith(rTile)) 
        { 
         int maxUnit = wUnit > hUnit ? wUnit : hUnit; 

         br.ResetTransform(); 
         br.ScaleTransform((float)maxUnit * (float)Math.Sqrt(2d), (float)maxUnit * (float)Math.Sqrt(2d), MatrixOrder.Append); 
         br.RotateTransform(45f, MatrixOrder.Append); 
         br.TranslateTransform(wUnit * wStep, hUnit * hStep, MatrixOrder.Append); 

         e.Graphics.FillRectangle(br, rTile); 

         br.ResetTransform(); 
        } 
       } 
      } 
     } 

     private void Form1_Resize(object sender, EventArgs e) 
     { 
      this.Invalidate(); 
     } 
    } 
} 

Oto zrzut wyjścia:

5x5 Form with Gradient-Tile Painting

+0

Wygląda na to, że mamy tutaj dużo więcej do zrobienia. Rozważę użycie pędzla dla każdego prostokąta i zobaczę, jak to działa. W celu wyjaśnienia. – Eugen

+0

Eugen, zmierz. Zobacz, jaka jest najlepsza metoda. Możesz użyć czegoś prostego, jako dwóch datetimes. – Andres

Powiązane problemy