填充面板有三种颜色的渐变

Bug*_*234 7 c# color-picker colors lineargradientbrush winforms

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

所以我决定它将成为Win Forms App中具有此背景的Panel.

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

gu0oJ.png

但我找不到任何有关我应该用于此的信息.

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

{
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);
    }
}
Run Code Online (Sandbox Code Playgroud)

}

现在我有了这个渐变的面板

ORnzf.png

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

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

TaW*_*TaW 16

以下是LinearGradientBrushPaint事件中使用多色的示例:

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);
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

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

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

要获得单击的颜色,您可以编写代码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);
    }
}
Run Code Online (Sandbox Code Playgroud)

如果你想捕获很多点击,最好保持Bitmap一个类级变量,而不是一直重新创建它.将它设置为Panel的BackgroundImage,因为Kala的答案假定也可能是一个不错的选择..

这应该回答标题中的问题.但是,您的第一张图片不会显示三种颜色的渐变.它显示了具有四种颜色的2D渐变.对于这种更昂贵的着色方法,你应该把颜色放在一个Bitmap并设置为Panel's BackgroundImage..

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

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;
}
Run Code Online (Sandbox Code Playgroud)

以下是您使用它的方式:

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

这使用简单,LinearGradientBrushes没有额外的颜色列表在高度上下降Panel.

请注意,这Color.Green是一个相当暗的色调,所以我用FromRgb了一个更亮的绿色.如果您的Panel像素大于256像素,则可能需要通过填充较大的条带进行优化; ifs它是垂直的你可能想要改变循环来超过x而不是y ..

结果如下:

在此输入图像描述

要点击一下,您现在只需从以下颜色中读出颜色BackgroundImage:

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

更新2:

查看此MSDN页面时,我们发现实际上有一个内置工具来创建2D渐变.

它是PathGradientBrush

这是一个例子..:

在此输入图像描述

..和代码:

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;
}
Run Code Online (Sandbox Code Playgroud)

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

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)};
}
Run Code Online (Sandbox Code Playgroud)

另一个计算a的中值颜色List<Color>.这用作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);
}
Run Code Online (Sandbox Code Playgroud)

结果与使用条纹的结果非常相似LinearGradientBrushes.它更简单,应该更好一点; 这是我明显推荐的......

注意改变颜色(或角落)的顺序!在SurroundColors适用于相反的矩形的角落..

注意:

在研究该页面时,可以发现该刷子实际上有四种不同的用途.

它们在如何设置(GraphicsPathPoint[]),填充(SurroundColorsInterpolationColors.Colors)的颜色集合以及如何调用它(具有形状或路径)方面有所不同.结果也差异很大.

另请注意,虽然提供了所有四种代码,但只显示了三种结果或四种方式!