2013-02-25 17 views
5

我正在生成一堆具有不同大小和位置的RectangleF對象。在GDI +中使用漸變刷子填充它們的最佳方式是什麼?繪製漸變矩形的有效方法

在WPF中,我可以創建一個LinearGradientBrush,設置開始和結束點relative點和WPF將照顧其餘。

但是,在GDI +中,漸變畫筆構造函數需要絕對座標中的位置,這意味着我必須爲每個矩形創建一個畫筆,這將是一個非常複雜的操作。

我錯過了什麼或者那確實是唯一的方法嗎?

回答

0

,我建議你創建這樣一個通用的方法:

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

然後,對於每一個矩形只要致電:

yourrectangleF.Paint += new PaintEventHandler(Paint_rectangle); 

如果gradrients顏色都是一樣的,你可以使方法更短。希望有所幫助..

+1

這不利於對我的恐懼創建每個矩形漸變畫筆的。我確實有2個筆刷,我需要用來繪製1000個矩形。 – Eugen 2013-02-25 19:08:44

+0

對不起隊友,但我想你沒有別的選擇。我遇到性能問題,您可以使用線程來改進它。你可以減少時間。現在通過爲每個矩形創建一個LinearGradientBrush來填充所有矩形需要多長時間? – Andres 2013-02-25 19:14:00

+0

我還沒有測試,只是希望有相同的刷創建過程中的WPF,並有一個想法,我失去了一些東西。但看起來這是唯一的方法。 – Eugen 2013-02-25 19:18:13

1

如果您只想聲明一次畫筆,您可以在應用漸變之前的那一刻指定一個變形。請注意,使用轉換將覆蓋許多可在LinearGradientBrush上指定的構造函數參數。

LinearGradientBrush.Transform Property (System.Drawing.Drawing2D)

要修改轉換,調用對應於所需矩陣運算刷對象的方法。請注意,矩陣操作不可交換,所以順序很重要。出於您的目的,您可能需要按照以下順序對它們進行縮放,旋轉,偏移/平移。

LinearGradientBrush.ResetTransform Method @ MSDN

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

LinearGradientBrush.RotateTransform Method (Single, MatrixOrder) @ MSDN

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

需要注意的是系統級的繪圖工具實際上並不包含股票定義爲漸變畫筆,所以如果你有性能問題關於製作多個畫筆,創建大量漸變畫筆不應該比GDI +/System.Drawin的開銷花費更多g維護定義漸變和樣式所需的數據。您可以根據需要創建每個矩形的畫筆,而不必深入到通過變換自定義畫筆所需的數學中。

Brush Functions (Windows) @ MSDN

這裏是你可以在一個WinForms應用程序測試的代碼示例。這個應用程序使用漸變畫筆使用45度漸變繪製瓷磚,縮放到瓷磚的最大尺寸(天真計算)。如果你操縱值和轉換,你可能會發現如果你有非平凡的漸變定義,使用爲所有矩形設置變換的技術是不值得的。否則,請記住,您的轉換適用於世界級別,而在GDI世界中,y軸是顛倒的,而在笛卡爾式數學世界中,它是從下到上排列的。這也導致角度順時針應用,而在三角中,角度沿y軸向上增加值逆時針方向前進。

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

下面是一個輸出的快照:

5x5 Form with Gradient-Tile Painting

+0

它看起來像我這裏我們有更多的計算要做。我會考慮使用每個矩形的畫筆,看看它是如何去。 Thx的澄清。 – Eugen 2013-02-25 21:09:01

+0

尤金,衡量它。並看看最好的方法是什麼..你可以使用簡單的兩個日期時間。 – Andres 2013-02-25 23:54:06