不知道你使用LinearGradientBrush的时候,是否会遇到这样的情况,在图形的顶部出现一条横线,颜色为渐变色底部的颜色,如图:
下面我们将详细的了解一下LinearGradientBrush,并解释为何会存在上面的问题。
关于LinearGradientBrush的两个Rectangle
我们以构造函数LinearGradientBrush(Rectangle, Color, Color, LinearGradientMode)为例,两个Rectangle是指New LinearGradientBrush时传入的Rectangle和Graphics.FillRectangle时传入的Rectangle。我们很多时候都会写这样的代码,在事先计算好的rect中来填充渐变色:
Rectangle rect = new Rectangle(0, 10, 100, 24); LinearGradientBrush brush = new LinearGradientBrush(rect, Color.LightGreen, Color.Blue, LinearGradientMode.Vertical); g.FillRectangle(brush, rect);
这样并看不出来这两个Rectangle有什么区别。
那么我们可以把后者Rectangle放大,宽度x2,高度x4,来看看区别
int top = 10; int height = 24; Rectangle rect = new Rectangle(0, top, 150, height); LinearGradientBrush brush = new LinearGradientBrush(rect, Color.LightGreen, Color.Blue, LinearGradientMode.Vertical); rect.Width = 300; rect.Height = height * 4; g.FillRectangle(brush, rect); brush.Dispose();
效果如下:
可以看到,当要填充的区域大于笔刷的区域时,会以平铺的效果显示。
(水平效果好像是拉伸了,请其实也是平铺的,只不过两个一样的笔刷连着放在一个水平线上,之间没有间隔,看起来是一个而已,其实是两个)
结论1:使用FillRectangle方法时,是使用平铺的效果来显示笔刷的,不是拉伸。
假如我们将上述的代码稍微修改,FillRectangle时将rect的Y减小1个像素:
private void panel2_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; int top = 10; int height = 24; Rectangle rect = new Rectangle(0, top, 150, height); LinearGradientBrush brush = new LinearGradientBrush(rect, Color.LightGreen, Color.Blue, LinearGradientMode.Vertical); rect.Width = 300; rect.Height = height * 4; rect.Y -= 1; g.FillRectangle(brush, rect); brush.Dispose(); }
得到结果:
文章开头提出的现象出现了。
结论2:当FillRectangle的rect和LinearGradientBrush的rect不一致的时候,如果FillRectangle的rect的顶部多一些内容,这部分内容将用渐变的底部颜色填充。
这个是一种情况,很好理解,那么接下来的一种情况就未必了,请看下文。
能不能定义一个LinearGradientBrush在多处使用呢
假如我们想实现下图的效果,能不能用同一个LinearGradientBrush呢?
我们用如下的代码实现:
private void panel1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; int top = 0; int height = 23; Rectangle rect = new Rectangle(0, top, this.panel1.Width, height); LinearGradientBrush brush = new LinearGradientBrush(rect, Color.LightGreen, Color.Blue, LinearGradientMode.Vertical); g.FillRectangle(brush, rect); rect.Offset(0, height * 2); g.FillRectangle(brush, rect); rect.Offset(0, height * 2); g.FillRectangle(brush, rect); rect.Offset(0, height * 2); g.FillRectangle(brush, rect); brush.Dispose(); }
可是我们却得到的是这样的效果:
这个问题又出现了!
既然用同一个LinearGradientBrush不行,那我们用不同的行不行呢,再看代码:
private void panel1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; int top = 0; int height = 23; Rectangle rect = new Rectangle(0, top, this.panel1.Width, height); LinearGradientBrush brush = new LinearGradientBrush(rect, Color.LightGreen, Color.Blue, LinearGradientMode.Vertical); g.FillRectangle(brush, rect); rect.Offset(0, height * 2); LinearGradientBrush brush2 = new LinearGradientBrush(rect, Color.LightGreen, Color.Blue, LinearGradientMode.Vertical); g.FillRectangle(brush2, rect); rect.Offset(0, height * 2); LinearGradientBrush brush3 = new LinearGradientBrush(rect, Color.LightGreen, Color.Blue, LinearGradientMode.Vertical); g.FillRectangle(brush3, rect); rect.Offset(0, height * 2); LinearGradientBrush brush4 = new LinearGradientBrush(rect, Color.LightGreen, Color.Blue, LinearGradientMode.Vertical); g.FillRectangle(brush4, rect); brush.Dispose(); brush2.Dispose(); brush3.Dispose(); brush4.Dispose(); }
效果如何呢?
同样是不行!那么问题究竟出在哪里?
上面的代码中创建了4个笔刷,后3个有问题,为了更简便我们提取第二个来分析问题:
private void panel1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; int top = 0; int height = 23; Rectangle rect = new Rectangle(0, top + height * 2, this.panel1.Width, height); LinearGradientBrush brush2 = new LinearGradientBrush(rect, Color.LightGreen, Color.Blue, LinearGradientMode.Vertical); g.FillRectangle(brush2, rect); brush2.Dispose(); }
即上面的代码会得到如下的结果:
我们把上面的代码改一点点,高度从23变为24
private void panel1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; int top = 0; int height = 24; Rectangle rect = new Rectangle(0, top + height * 2, this.panel1.Width, height); LinearGradientBrush brush2 = new LinearGradientBrush(rect, Color.LightGreen, Color.Blue, LinearGradientMode.Vertical); g.FillRectangle(brush2, rect); brush2.Dispose(); }
一下子就能正常显示了:
没错,就是高度的问题引起的。
使用LinearGradientBrush的最佳做法
经测试发现,当创建LinearGradientBrush的时候如果rect高度为偶数,就不会有问题,如果是奇数,就会出现问题。
根据结论2我们可以这样理解:某些情况下,当创建高度为奇数的LinearGradientBrush笔刷时,其实创建的是高度-1的笔刷,当我们再往原来的Rectangle中填充的时候,填充区域比笔刷区域大,在顶部多了一块,那么这一块将会用渐变的底部颜色填充,所以上面有一条蓝色的线。
为什么上面要说在“某些情况下”呢?我们将代码再改一点点,把rect的Y坐标改为0:
private void panel1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; int top = 0; int height = 23; Rectangle rect = new Rectangle(0, top + height * 2, this.panel1.Width, height); rect.Y = 0; LinearGradientBrush brush2 = new LinearGradientBrush(rect, Color.LightGreen, Color.Blue, LinearGradientMode.Vertical); g.FillRectangle(brush2, rect); brush2.Dispose(); }
发现问题不存在了:
实际上,把Y坐标改为1,也不会有问题。
结论3:
当我们在使用LinearGradientBrush填充rectangle的时候,最好把高度设置为偶数。
如果非要是奇数,最好把创建LinearGradientBrush的rectangle高度加1变为偶数,这样在任何情况下都不会有问题。
如下面的代码,即使在Y坐标不为0或1的时候,也能准确的画出渐变:
private void panel1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; int top = 0; int height = 23; Rectangle rect = new Rectangle(0, top + height * 2, this.panel1.Width, height); Rectangle rectBrush = rect; if (rectBrush.Height % 2 == 1) { rectBrush.Height += 1; } LinearGradientBrush brush2 = new LinearGradientBrush(rectBrush, Color.LightGreen, Color.Blue, LinearGradientMode.Vertical); g.FillRectangle(brush2, rect); brush2.Dispose(); }
效果图:
本文章由创风网原创,转载请注明出处:http://www.windite.com/article/details/qti25q8