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(位图);”方法同上。。请注意,您的原始代码是