用三种颜色的渐变填充面板 [英] Fill Panel with gradient in three colors

查看:24
本文介绍了用三种颜色的渐变填充面板的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在做项目,我必须使用 C# 做一些颜色选择器.

所以我决定在 Win Forms App 中使用这个背景的面板.

背景应具有 rgb 中三种颜色的渐变:红色 (0 - 255)、蓝色 (0 - 255) 和绿色 = 0.

但是我找不到关于我应该使用什么的任何信息.

我尝试编写一些代码,这就是我所做的.

<代码>{公共部分类 Form1 :表单{公共 Form1(){初始化组件();}private void Form1_Load(对象发送者,EventArgs e){panel1.Paint += new PaintEventHandler(panel1_Paint);panel1.Refresh();}private void panel1_Paint(对象发送者,PaintEventArgs e){点起点 = 新点(0, 0);点端点 = 新点(150, 150);LinearGradientBrush lgb =new LinearGradientBrush(startPoint, endPoint, Color.FromArgb(255, 255, 0, 0), Color.FromArgb(255, 255, 255, 0));图形 g = e.Graphics;g.FillRectangle(lgb, 0, 0, 150, 150);//g.DrawLine(new Pen(Color.Yellow, 1.5f), startPoint, endPoint);}}

}

现在我有这个渐变的面板

我应该用什么来获得第一张图片的渐变?

第二个问题:点击这个背景后我应该怎么做才能获得像素颜色?

解决方案

以下是在 Paint 事件中使用多色 LinearGradientBrush 的示例:

LinearGradientBrush linearGradientBrush =new LinearGradientBrush(panel4.ClientRectangle, Color.Red, Color.Yellow, 45);ColorBlend cblend = new ColorBlend(3);cblend.Colors = new Color[3] { Color.Red, Color.Yellow, Color.Green };cblend.Positions = new float[3] { 0f, 0.5f, 1f };linearGradientBrush.InterpolationColors = cblend;e.Graphics.FillRectangle(linearGradientBrush, panel4.ClientRectangle);

您可以自由改变停止点的颜色数量、角度或扩展.只需确保您始终拥有相同数量的颜色和停止点,并让它们从 0 开始到 1 结束.

忽略构造函数中的颜色,顺便说一句..

要获得点击的颜色,您可以对 MouseClick 进行编码:

Color clickedColor = Color.Empty;private void panel_MouseClick(对象发送者,MouseEventArgs e){使用 (Bitmap bmp = new Bitmap( panel.ClientSize.Width, panel4.ClientSize.Height)){panel.DrawToBitmap(bmp,panel.ClientRectangle);clickedColor = bmp.GetPixel(e.X, e.Y);}}

如果您想获得多次点击,最好将 Bitmap 保留在类级别变量中,而不是一直重新创建它.. 将其设置为面板的背景图像,正如 Kala 的回答所假设的也可能是一个不错的选择..

这应该回答标题中的问题.但是,您的第一张图片没有显示三种颜色的渐变.它显示了具有四种颜色的 2D 渐变.对于这种更昂贵的着色方法,您应该将颜色放入 Bitmap 并将其设置为 PanelBackgroundImage..

Update1 这是一段创建 2D 渐变的代码:

Bitmap Gradient2D(矩形r,颜色c1,颜色c2,颜色c3,颜色c4){Bitmap bmp = new Bitmap(r.Width, r.Height);浮动 delta12R = 1f * (c2.R - c1.R)/r.Height;浮动 delta12G = 1f * (c2.G - c1.G)/r.Height;浮动 delta12B = 1f * (c2.B - c1.B)/r.Height;浮动 delta34R = 1f * (c4.R - c3.R)/r.Height;浮动 delta34G = 1f * (c4.G - c3.G)/r.Height;浮动 delta34B = 1f * (c4.B - c3.B)/r.Height;使用(图形 G = Graphics.FromImage(bmp) )for (int y = 0; y 

这是你如何使用它:

 public Form1(){初始化组件();panel.BackgroundImage = Gradient2D(panel.ClientRectangle,Color.Black, Color.FromArgb(255, 0, 255, 0), Color.Red, Color.Yellow);}

这使用了简单的LinearGradientBrushes,而没有一个额外的颜色列表向下超过Panel的高度.

请注意,Color.Green 是一种相当暗的色调,因此我使用 FromRgb 来获得更亮的绿色.如果您的 Panel 大于 256 像素,您可能希望通过填充更大的条纹进行优化;如果它是垂直的,您可能需要更改循环以遍历 x 而不是 y..

结果如下:

要点击选择,您现在只需从 BackgroundImage 中读出颜色:

private void panel_MouseClick(object sender, MouseEventArgs e){clickedColor = ((Bitmap)panel.BackgroundImage).GetPixel(e.X, e.Y);}

更新 2:

查看

.. 和代码:

Bitmap Gradient2D(矩形r,颜色c1,颜色c2,颜色c3,颜色c4){列表<颜色>颜色 = 新列表<颜色>{ c1, c3, c4, c2 };Bitmap bmp = new Bitmap(r.Width, r.Height);使用(图形 g = Graphics.FromImage(bmp))for (int y = 0; y 

这使用了两个简单的辅助函数.一个返回矩形的角点:

public ListgetCorners(RectangleF r){return new List() { r.Location, new PointF(r.Right, r.Top),new PointF(r.Right, r.Bottom), new PointF(r.Left, r.Bottom)};}

另一个从 List 计算中间颜色.这用作 CenterColor..:

public static Color mediumColor(List cols){int c = cols.Count;返回 Color.FromArgb(cols.Sum(x => x.A)/c, cols.Sum(x => x.R)/c,cols.Sum(x => x.G)/c, cols.Sum(x => x.B)/c);}

结果与使用 LinearGradientBrushes 条纹的结果几乎相同.它更简单,性能应该更好一些;这是我显然会推荐的..

注意颜色(或角)的改变顺序SurroundColors 适用于矩形的对角..

注意:

在研究该页面时,您会发现该画笔实际上有四种不同的用途.

它们的不同之处在于如何设置(GraphicsPathPoint[]),填充哪些颜色集合(SurroundColors>InterpolationColors.Colors)以及如何调用它(使用形状或路径).而且结果也相差很大.

另请注意,尽管提供了所有四种方式的代码,但仅显示了四种方式的三种结果!...

I'm working on project and I have to do kind of color picker using C#.

So I've decided that it will be a Panel with this background in Win Forms App.

Background should have gradient with three colors in rgb: red (0 - 255), blue (0 - 255) and green = 0.

But I can't find any information about what I should use for this.

I tried to write some code and here is what I've done.

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



    private void Form1_Load(object sender, EventArgs e)
    {
        panel1.Paint += new PaintEventHandler(panel1_Paint);
        panel1.Refresh();
    }

    private void panel1_Paint(object sender, PaintEventArgs e)
    {
        Point startPoint = new Point(0, 0);
        Point endPoint = new Point(150, 150);

        LinearGradientBrush lgb =
            new LinearGradientBrush(startPoint, endPoint,     Color.FromArgb(255, 255, 0, 0), Color.FromArgb(255, 255, 255, 0));
        Graphics g = e.Graphics;
        g.FillRectangle(lgb, 0, 0, 150, 150);
       // g.DrawLine(new Pen(Color.Yellow, 1.5f), startPoint, endPoint);
    }
}

}

And now I have panel with this gradient

What I should use to get gradient at first picture?

And second question: What should I do to get the pixel color after clicking on this background?

解决方案

Here is an example for using a multicolor LinearGradientBrush in the Paint event:

LinearGradientBrush linearGradientBrush =
   new LinearGradientBrush(panel4.ClientRectangle, Color.Red, Color.Yellow, 45);

ColorBlend cblend = new ColorBlend(3);
cblend.Colors = new Color[3]  { Color.Red, Color.Yellow, Color.Green };
cblend.Positions = new float[3] { 0f, 0.5f, 1f };

linearGradientBrush.InterpolationColors = cblend;

e.Graphics.FillRectangle(linearGradientBrush, panel4.ClientRectangle);

You can freely vary the number of colors, the angle or the spread of the stop points. Just make sure you always have the same number of colors and stop points and let them start at 0 and end at 1.

The colors in the constructor are ignored, btw..

To get a clicked color you can code the MouseClick:

Color clickedColor = Color.Empty;

private void panel_MouseClick(object sender, MouseEventArgs e)
{
    using (Bitmap bmp = new Bitmap( panel.ClientSize.Width, panel4.ClientSize.Height))
    {
        panel.DrawToBitmap(bmp,panel.ClientRectangle);
        clickedColor = bmp.GetPixel(e.X, e.Y);
    }
}

If you want to catch many clicks it may be better to keep the Bitmap in a class level variable instead of recreating it all the time.. Setting it as the Panel's BackgroundImage, as Kala's answer assumes may also be a good option..

This should answer the question in the title. However your first image doesn't show a gradient with three colors. It shows a 2D gradient with four colors. For such a more expensive coloring method you should put the colors in a Bitmap and set it as the Panel's BackgroundImage..

Update1 Here is a piece of code that creates a 2D Gradient:

Bitmap Gradient2D(Rectangle r, Color c1, Color c2, Color c3, Color c4)
{
    Bitmap bmp = new Bitmap(r.Width, r.Height);

    float delta12R = 1f * (c2.R - c1.R) / r.Height;
    float delta12G = 1f * (c2.G - c1.G) / r.Height;
    float delta12B = 1f * (c2.B - c1.B) / r.Height;
    float delta34R = 1f * (c4.R - c3.R) / r.Height;
    float delta34G = 1f * (c4.G - c3.G) / r.Height;
    float delta34B = 1f * (c4.B - c3.B) / r.Height;
    using (Graphics G = Graphics.FromImage(bmp) )
    for (int y = 0; y < r.Height; y++)
    {
        Color c12 = Color.FromArgb(255,  c1.R + (int)(y * delta12R), 
              c1.G + (int)(y * delta12G), c1.B + (int)(y * delta12B));
        Color c34 = Color.FromArgb(255, c3.R + (int)(y * delta34R), 
              c3.G + (int)(y * delta34G), c3.B + (int)(y * delta34B));
        using ( LinearGradientBrush lgBrush = new LinearGradientBrush(
              new Rectangle(0,y,r.Width,1), c12, c34, 0f) )
        {  G.FillRectangle(lgBrush, 0, y, r.Width, 1);  }
    }
    return bmp;
}

Here is how you use it:

    public Form1()
    {
        InitializeComponent();
        panel.BackgroundImage = Gradient2D(panel.ClientRectangle, 
               Color.Black, Color.FromArgb(255, 0, 255, 0), Color.Red, Color.Yellow);
    }

This uses simple LinearGradientBrushes without an extra colors list going down over the height of the Panel.

Note that Color.Green is a rather dark hue, so I used FromRgb for a brighter green. If your Panel is greater than 256 pixels you may want to optimze by filling larger stripes; if it is vertical you may want to change the loop to go over x instead of y..

Here is the result:

To pick with a click you now simply read out the color from the BackgroundImage:

private void panel_MouseClick(object sender, MouseEventArgs e)
{
    clickedColor = ((Bitmap)panel.BackgroundImage).GetPixel(e.X, e.Y);
}

Update 2:

When looking over this MSDN page we can find that there actually is a built-in tool to create 2D gradients.

It is the PathGradientBrush

Here is an example..:

.. and the code:

Bitmap Gradient2D(Rectangle r, Color c1, Color c2, Color c3, Color c4)
{
    List<Color> colors = new List<Color> {  c1, c3, c4, c2 };
    Bitmap bmp = new Bitmap(r.Width, r.Height);
    using (Graphics g = Graphics.FromImage(bmp))
    for (int y = 0; y < r.Height; y++)
    {

        using (PathGradientBrush pgb = new PathGradientBrush(getCorners(r).ToArray()))
        {
            pgb.CenterColor = medianColor(colors);
            pgb.SurroundColors = colors.ToArray();
            g.FillRectangle(pgb, 0, y, r.Width, 1);
        }
    }
    return bmp;
}

This uses two simple helper functions. One returns the corner points of a rectangle:

public List<PointF> getCorners(RectangleF r)
{
    return new List<PointF>() { r.Location, new PointF(r.Right, r.Top),
        new PointF(r.Right, r.Bottom), new PointF(r.Left, r.Bottom)};
}

The other calculates a median color from a List<Color>. This is used as the CenterColor..:

public static Color medianColor(List<Color> cols)
{
    int c = cols.Count;
    return Color.FromArgb(cols.Sum(x => x.A) / c, cols.Sum(x => x.R) / c,
        cols.Sum(x => x.G) / c, cols.Sum(x => x.B) / c);
}

The result pretty much identical to the one from using stripes of LinearGradientBrushes. It is simpler and should perform a bit better; it is what I would recommend obviously..

Note the changed order of the colors (or corners)! The SurroundColors apply to opposing corners of the rectangle..

Note:

When studying that page one can find that there actually are four different uses for that brush.

They differ in how to set it up (GraphicsPath or Point[]), which color collections to fill (SurroundColors or InterpolationColors.Colors) and how to call it (with a shape or a path). And the results also differ a lot.

Also note that only three results of the four ways are shown, although code for all four is provided!..

这篇关于用三种颜色的渐变填充面板的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆