我使用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;
}
}
注意:是的,我知道.CreateGraphics
不是一个好的绘图方法,它有一个与问题无关的独特目的。
答案 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());
几乎总是错误的,只要你超越一个非持久的绘图操作就会受到伤害。
以下是完整代码:
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
调用正在对数据进行复制,因此我们不会清除刚刚添加到列表列表中的实例!