您面临的问题是使用固定大小的数组。每个条目默认为一个点(0,0)
所以Drawlines()
方法绘制 10 个元素,甚至是那些不是通过鼠标单击设置的元素。这导致最后几个点从原点开始(0,0)
。此外,还有一个有缺陷的实现,即要保留哪些点击以及使用时发生了多少次点击kliks
and lijst
为了同样的事情。
这是 C#,最好学习如何分离跟踪鼠标点击的数据模型和绘制线条的显示代码。
PointHistory.cs
考虑以下使用数组的类Point
跟踪鼠标点击。该类使用要保留的最大点数进行初始化(例如,10)。有一些方法可以添加点AddPoint(point)
并删除最旧的点RemoveFirstPoint()
。定义的点数可通过.Count
财产。
最后,GetPoints()
方法,返回仅包含已定义元素的数组副本。该方法用在绘制线条的代码中。
using System;
using System.Linq;
public class PointHistory
{
private readonly Point[] points;
private readonly int maxPoints;
private int count;
public PointHistory(int pointCapacity)
{
count = 0;
maxPoints = pointCapacity;
points = new Point[pointCapacity];
}
public Point[] GetPoints() { return points.Take(count).ToArray(); }
public int Count { get => count; }
public int Capacity { get => maxPoints; }
public void AddPoint(Point point)
{
if (count < maxPoints)
{
points[count++] = point;
}
}
public void RemoveFirstPoint()
{
if (count > 0)
{
for (int i = 0; i < count - 1; i++)
{
points[i] = points[i + 1];
}
count--;
}
}
}
Form1.cs
另一个问题是你的绘图,它需要发生在Paint
事件处理程序。用你的MouseClick
修改点列表的事件,以及Paint
进行绘图的事件。
public partial class Form1 : Form
{
readonly PointHistory history;
public Form1()
{
InitializeComponent();
history = new PointHistory(10);
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
this.MouseClick += Form1_MouseClick;
this.Paint += Form1_Paint;
}
private void Form1_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
history.AddPoint(e.Location);
}
else if (e.Button == MouseButtons.Right)
{
history.RemoveFirstPoint();
history.AddPoint(e.Location);
}
this.Invalidate();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
if (history.Count >= 2)
{
e.Graphics.DrawLines(Pens.Blue, history.GetPoints());
}
foreach (var point in history.GetPoints())
{
e.Graphics.FillEllipse(Brushes.Blue, point.X - 2, point.Y - 2, 4, 4);
}
}
}
我添加了一些额外的代码来在鼠标点击时添加小点以获得更好的视觉效果。
左键单击尝试将点添加到鼠标单击的历史记录中,最多达到构造函数中设置的限制PointHistory
。单击鼠标右键会先删除最旧的点,然后再添加新点。
根据评论,我想提供一个下面的版本,它没有为逻辑定义单独的类,并且一切都是在内部完成的Form1
班级。也没有高级库,例如Linq
被使用
public partial class Form1 : Form
{
private readonly Point[] points;
private int count;
public Form1()
{
InitializeComponent();
points = new Point[10];
count = 0;
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
this.Paint += Form1_Paint;
this.MouseClick += Form1_MouseClick;
}
public Point[] GetPoints()
{
Point[] results = new Point[count];
for (int i = 0; i < count; i++)
{
results[i] = points[i];
}
return results;
// Alternative to the loop above
//
//Array.Copy(points, results, count);
//return results;
}
public void AddPoint(Point point)
{
if (count < points.Length)
{
points[count++] = point;
}
}
public void RemoveFirstPoint()
{
if (count > 0)
{
for (int i = 0; i < count - 1; i++)
{
points[i] = points[i + 1];
}
count--;
}
}
private void Form1_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
AddPoint(e.Location);
}
else if (e.Button == MouseButtons.Right)
{
RemoveFirstPoint();
AddPoint(e.Location);
}
this.Invalidate();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
Point[] mouseClicks = GetPoints();
if (count >= 2)
{
e.Graphics.DrawLines(Pens.Blue, mouseClicks);
}
foreach (var point in mouseClicks)
{
e.Graphics.FillEllipse(Brushes.Blue, point.X - 2, point.Y - 2, 4, 4);
}
}
}
主要看方法是GetPoints()
它返回一个点数组have通过鼠标单击定义并忽略任何尚未定义的点。
有一个替代实现,注释了用途Array.Copy()
而不是循环,这将有助于更好的实现。