C# 防止Alpha彩色笔重叠?

C# 防止Alpha彩色笔重叠?,c#,winforms,graphics,C#,Winforms,Graphics,我有一个使用笔对象的简单荧光灯。当尺寸非常大时,它会创建奇怪的条纹,您可以通过使用System.Drawing.Drawing2D.LineCap.Round定义其起始和结束封口来修复,但它会立即重叠并失去透明度。当您多次在平顶上绘制时,平顶也会失去透明度 如何创建不重叠的不透明笔,或创建笔宽较大的条纹 private static Color baseColor = Color.Yellow; bool Draw; Graphics g; Point start; Point end;

我有一个使用
对象的简单荧光灯。当尺寸非常大时,它会创建奇怪的条纹,您可以通过使用
System.Drawing.Drawing2D.LineCap.Round
定义其起始和结束封口来修复,但它会立即重叠并失去透明度。当您多次在平顶上绘制时,平顶也会失去透明度

如何创建不重叠的不透明笔,或创建笔宽较大的条纹

private static Color baseColor = Color.Yellow;
bool Draw;
Graphics g;
Point start;
Point end;

     private void Form1_Load(object sender, EventArgs e)
    {
        g = this.CreateGraphics();
        Pen1.Color = Color.FromArgb(128, baseColor);
        Pen1.Width = 50;
        Pen1.StartCap = System.Drawing.Drawing2D.LineCap.Flat; //I know it's default, just for clarification's sake
        Pen1.EndCap = System.Drawing.Drawing2D.LineCap.Flat;   //' '''' '' ' '''''''  '''' ''' ''''''''''''' ' ''''
    }

     private void Form1_MouseDown(object sender, MouseEventArgs e)
    {
        Draw = true;
        start = e.Location;
    }

     private void Form1_MouseUp(object sender, MouseEventArgs e)
    {
        Draw = false;
    }

    private void Form1_MouseMove(object sender, MouseEventArgs e)
    {
        if (Draw == true)
        {
            end = e.Location;
            g.DrawLine(Pen1, start, end);
            start = end;
        }
    }
它的行为是这样的


注意:是的,我知道
。CreateGraphics
不是一种好的绘图方法,它有一个与问题无关的独特用途。

绘图对象有两个问题:

  • 你分别画每一条线;这将在公共点重叠处创建丑陋的瑕疵。相反,使用
    DrawLines
    方法一次画完所有线条!(注意复数形式!)

  • 您没有限制
    笔。MiterLimit
    ;当直线方向急剧变化时,会产生难看的尖峰。尝试将其限制在
    笔宽的1/2左右或更小。还建议设置
    LineJoin
    以及两个
    Caps

MouseMove
中的
列表currentPoints
中收集当前行的点,并在
MouseUp
中收集
currentList
列表所有点列表中

然后,您可以在
Paint
事件中同时绘制这两个图形

    foreach (List<Point> points in allPointLists)
        if (points.Count > 1) e.Graphics.DrawLines(Pens.Gold, points.ToArray());
    if (currentPoints.Count > 1) e.Graphics.DrawLines(Pens.Gold, currentPoints.ToArray());
下面是
绘制
事件;请注意,我对当前绘制的线条和旧线条使用了两种不同的
笔。还请注意,您可以使用
DrawCurve
而不是
DrawLines
来获得更平滑的结果

还要注意的是,我使用
列表
灵活地计算元素的数量,并在
绘制
命令中将其转换为数组

private void Form1_Paint(object sender, PaintEventArgs e)
{
    Color c1 = Color.FromArgb(66, 77, 88, 222);
    using (Pen pen = new Pen(c1, 50f))
    {
        pen.MiterLimit = pen.MiterLimit / 12;
        pen.LineJoin = LineJoin.Round;
        pen.StartCap = LineCap.Round;
        pen.EndCap = LineCap.Round;
        foreach (List<Point> points in allPointLists)
            if (points.Count > 1) e.Graphics.DrawLines(pen, points.ToArray());
    }
    Color c2 = Color.FromArgb(66, 33, 111, 222);

    using (Pen pen = new Pen(c2, 50f))
    {
        pen.MiterLimit = pen.MiterLimit / 4;
        pen.LineJoin = LineJoin.Round;
        pen.StartCap = LineCap.Round;
        pen.EndCap = LineCap.Round;
        if (currentPoints.Count > 1) e.Graphics.DrawLines(pen, currentPoints.ToArray());
    }
}

注意
MouseUp
代码中的两个小更正,这是正确处理
currentPoints
列表所需的!清理是明显的;
ToList()
调用正在对数据进行复制,因此我们不清除刚刚添加到列表列表中的实例

图形对象有两个问题:

  • 你分别画每一条线;这将在公共点重叠处创建丑陋的瑕疵。相反,使用
    DrawLines
    方法一次画完所有线条!(注意复数形式!)

  • 您没有限制
    笔。MiterLimit
    ;当直线方向急剧变化时,会产生难看的尖峰。尝试将其限制在
    笔宽的1/2左右或更小。还建议设置
    LineJoin
    以及两个
    Caps

MouseMove
中的
列表currentPoints
中收集当前行的点,并在
MouseUp
中收集
currentList
列表所有点列表中

然后,您可以在
Paint
事件中同时绘制这两个图形

    foreach (List<Point> points in allPointLists)
        if (points.Count > 1) e.Graphics.DrawLines(Pens.Gold, points.ToArray());
    if (currentPoints.Count > 1) e.Graphics.DrawLines(Pens.Gold, currentPoints.ToArray());
下面是
绘制
事件;请注意,我对当前绘制的线条和旧线条使用了两种不同的
笔。还请注意,您可以使用
DrawCurve
而不是
DrawLines
来获得更平滑的结果

还要注意的是,我使用
列表
灵活地计算元素的数量,并在
绘制
命令中将其转换为数组

private void Form1_Paint(object sender, PaintEventArgs e)
{
    Color c1 = Color.FromArgb(66, 77, 88, 222);
    using (Pen pen = new Pen(c1, 50f))
    {
        pen.MiterLimit = pen.MiterLimit / 12;
        pen.LineJoin = LineJoin.Round;
        pen.StartCap = LineCap.Round;
        pen.EndCap = LineCap.Round;
        foreach (List<Point> points in allPointLists)
            if (points.Count > 1) e.Graphics.DrawLines(pen, points.ToArray());
    }
    Color c2 = Color.FromArgb(66, 33, 111, 222);

    using (Pen pen = new Pen(c2, 50f))
    {
        pen.MiterLimit = pen.MiterLimit / 4;
        pen.LineJoin = LineJoin.Round;
        pen.StartCap = LineCap.Round;
        pen.EndCap = LineCap.Round;
        if (currentPoints.Count > 1) e.Graphics.DrawLines(pen, currentPoints.ToArray());
    }
}

注意
MouseUp
代码中的两个小更正,这是正确处理
currentPoints
列表所需的!清理是明显的;
ToList()
调用正在对数据进行复制,因此我们不清除刚刚添加到列表列表中的实例

不要分开画线!!收集它们并使用抽绳(pl!)代替!!这样做可能会遇到问题,因为在绘制事件中绘制不正确。请看,避免基本错误通常不是无关紧要的,-)-也要查看钢笔。请将其限制在钢笔宽度的一半左右!你有一个例子片段吗?我已经将其转换为绘图线,方法是执行以下操作:
Point[]pts=newpoint[2]{start,end}
g.抽绳(Pen1,pts)和我设置
MiterLimit=50我仍然得到相同的结果。是的,你需要收集你所有的点,而不仅仅是两个使uip成为一行的点!只有在你解决了第一个问题后,miterlimit才会发挥作用。不要分开画线!!收集它们并使用抽绳(pl!)代替!!这样做可能会遇到问题,因为在绘制事件中绘制不正确。请看,避免基本错误通常不是无关紧要的,-)-也要查看钢笔。请将其限制在钢笔宽度的一半左右!你有一个例子片段吗?我已经将其转换为绘图线,方法是执行以下操作:
Point[]pts=newpoint[2]{start,end}
g.抽绳(Pen1,pts)和我设置
MiterLimit=50我仍然得到相同的结果。是的,你需要收集你所有的点,而不仅仅是两个使uip成为一行的点!只有在解决第一个问题后,miterlimit才会发挥作用。使用位图持久化图形方法而不是OnPaint,不可能创建相同的效果吗?我使用其他方法得到相同的结果,但当我使用OnPaint时,它可以工作。否则,这是一个很好的方法。当然,如果a)你有一个位图,b)你肯定有图形,你可以画成位图。您将仅使用currentPoints列表,并在鼠标悬停时将其绘制到位图中。但你的问题是关于在表格上画图的!?要绘制位图,请使用“Graphics g=Graphics.FromImage(位图);”方法同上。。请注意,您的原始代码是