防止Alpha彩色笔重叠?

时间:2016-03-16 20:42:36

标签: c# winforms graphics

我使用Pen对象有一个简单的荧光笔。当尺寸非常大时,它会产生奇怪的条纹,你可以通过定义它的开始和放大来修复它。结束上限为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;
        }
    }

它表现得像这样; Highlighter Example

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

1 个答案:

答案 0 :(得分:2)

绘图对象有两个问题:

  • 您分别绘制每一条线;这将创建公共点重叠的丑陋文物。而是使用DrawLines方法一次性绘制线条! (注意复数!)

  • 您没有限制Pen.MiterLimit;当线条方向急剧变化时,这会产生难看的尖峰。尝试将其限制在Pen.Width或更低的约1/2。还建议设置LineJoin以及两个Caps ..

List<Point> currentPoints的{​​{1}}中收集当前行的点数,并在MouseMove MouseUp上收集currentList }}

然后你可以在List<List<Point>> allPointLists事件中绘制..

Paint

注意它会立即支付费用,即使用有效的图形对象绘制 始终依赖{{ 1}}事件以确保始终根据需要更新图形!使用 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()); 几乎总是错误的,只要你超越一个非持久的绘图操作就会受到伤害。

enter image description here

以下是完整代码:

Paint

这是control.CreateGraphics事件;请注意,我对当前绘制的线条和较旧的线条使用了两个不同的List<Point> currentPoints = new List<Point>(); List<List<Point>> allPointLists = new List<List<Point>>(); private void Form1_MouseDown(object sender, MouseEventArgs e) { currentPoints = new List<Point>(); } private void Form1_MouseUp(object sender, MouseEventArgs e) { if (currentPoints.Count > 1) { allPointLists.Add(currentPoints.ToList()); currentPoints.Clear(); } } private void Form1_MouseMove(object sender, MouseEventArgs e) { if (e.Button == System.Windows.Forms.MouseButtons.Left) { currentPoints.Add(e.Location); Invalidate(); } } 。另请注意,您可以使用Paint代替Pens来获得更平滑的结果。

另请注意,我使用DrawCurve灵活地使用元素数量,并将其转换为DrawLines命令中的数组。

List<T>

为防止闪烁,请不要忘记为Draw打开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()); } } ;或使用DoubleBuffered子类或仅使用Form

最后说明:我忽略了简单点击的情况;如果他们应该画画你必须抓住他们,最好在DoubleBuffered Panel检查,最好在正确的地点做一个PictureBox并且尺寸正确..

<强>更新

if (points.Count > 1)非常有用,我几乎没有使用FillEllipse这些日子。以下是如何使用它来实现List<T>arrays按钮:

Clear

请注意Undo代码中的两个小修正,这需要正确处理private void buttonClear_Click(object sender, EventArgs e) { allPointLists.Clear(); Invalidate(); } private void buttonUndo_Click(object sender, EventArgs e) { allPointLists.Remove(allPointLists.Last()); Invalidate(); } 列表!清算很明显; MouseUp调用正在对数据进行复制,因此我们不会清除刚刚添加到列表列表中的实例!