在C#WinForm项目中显示移动像素的轨迹
我正在做一个与蚁群问题有关的个人项目。 我成功地为一个控制台项目开发了所有东西,现在我想用windows窗体将代码转换成更具图形化的布局 使用表单下方的代码可以正确显示一个移动的像素,但我无法找到显示移动的左轨迹的方法。我试图删除pictureBox1.Invalidate(),但这使我在起点处看到了一个静态像素 我不想重新分析地图矩阵并绘制信息素轨迹,只想留下绘制的位置,就像我在纸上用钢笔画东西一样在C#WinForm项目中显示移动像素的轨迹,c#,winforms,C#,Winforms,我正在做一个与蚁群问题有关的个人项目。 我成功地为一个控制台项目开发了所有东西,现在我想用windows窗体将代码转换成更具图形化的布局 使用表单下方的代码可以正确显示一个移动的像素,但我无法找到显示移动的左轨迹的方法。我试图删除pictureBox1.Invalidate(),但这使我在起点处看到了一个静态像素 我不想重新分析地图矩阵并绘制信息素轨迹,只想留下绘制的位置,就像我在纸上用钢笔画东西一样 public void RenderAnts(object sender, Paint
public void RenderAnts(object sender, PaintEventArgs e)
{
pictureBox1.Invalidate();
foreach (Ant a in ants)
{
Brush c;
c = Brushes.DarkBlue;
if (a.role == AntRole.Scout)
{
a.Move(i);
c = Brushes.Red;
}
e.Graphics.FillRectangle(c, a.position.x, a.position.y, 1, 1);
}
pictureBox1.Show();
}
添加列表
表单字段,其中点
是蚂蚁位置
字段的类型。在每个移动中
将当前蚂蚁位置添加到此列表。我模拟通过鼠标点击PictureBox
移动。绘制事件处理程序只是绘制位置
见样本
public partial class Form1 : Form
{
public Form1()
{
//InitializeComponent();
pictureBox1 = new PictureBox { Parent = this, Dock = DockStyle.Fill };
ants.Add(new Ant { Role = AntRole.Scout, Position = new Point(50, 50) });
ants.Add(new Ant { Role = AntRole.Scout, Position = new Point(150, 150) });
ants.Add(new Ant { Role = AntRole.Scout, Position = new Point(100, 100) });
pictureBox1.Paint += RenderAnts;
pictureBox1.Click += (s, e) =>
{
for (int i = 0; i < 100; i++)
foreach (Ant a in ants)
{
if (a.Role == AntRole.Scout)
{
a.Move();
antTrails.Add(a.Position);
}
}
pictureBox1.Refresh();
};
}
PictureBox pictureBox1;
List<Ant> ants = new List<Ant>();
List<Point> antTrails = new List<Point>();
public void RenderAnts(object sender, PaintEventArgs e)
{
foreach (var point in antTrails)
e.Graphics.FillRectangle(Brushes.Red, point.X, point.Y, 1, 1);
}
}
public class Ant
{
public AntRole Role;
public Point Position;
static Random rnd = new Random();
public void Move()
{
int r = rnd.Next(4);
if (r == 0)
Position.X--;
else if (r == 1)
Position.X++;
else if (r == 2)
Position.Y--;
else
Position.Y++;
}
}
public enum AntRole
{
Normal,
Scout
}
公共部分类表单1:表单
{
公共表格1()
{
//初始化组件();
pictureBox1=new PictureBox{Parent=this,Dock=DockStyle.Fill};
Add(新蚂蚁{Role=AntRole.Scout,Position=newpoint(50,50)});
Add(新的Ant{Role=AntRole.Scout,Position=newpoint(150150)});
Add(新的Ant{Role=AntRole.Scout,Position=newpoint(100100)});
pictureBox1.Paint+=渲染器;
pictureBox1.单击+=(s,e)=>
{
对于(int i=0;i<100;i++)
foreach(蚂蚁中的蚂蚁a)
{
if(a.Role==AntRole.Scout)
{
a、 Move();
添加(a.位置);
}
}
pictureBox1.Refresh();
};
}
PictureBox pictureBox1;
列表蚂蚁=新列表();
List antTrails=新列表();
公共无效渲染器(对象发送器、PaintEventArgs e)
{
foreach(antTrails中的变量点)
e、 图形.圆角矩形(画笔.Red,点.X,点.Y,1,1);
}
}
公共类蚂蚁
{
公共窦孔作用;
公共点位置;
静态随机rnd=新随机();
公开作废动议()
{
int r=rnd.Next(4);
如果(r==0)
位置X--;
else如果(r==1)
Position.X++;
else如果(r==2)
位置Y--;
其他的
Position.Y++;
}
}
公共上颌窦
{
正常,,
侦察兵
}
运行并尝试单击鼠标。这里有一个解决方案,它将轨迹绘制成位图,并将新蚂蚁绘制到曲面上: 准备位图:
Bitmap bmp = new Bitmap(pictureBox1.ClientSize.Width, pictureBox1.ClientSize.Height);
pictureBox1.Image = bmp;
现在,修改的绘制事件:
void RenderAnts(object sender, PaintEventArgs e)
{
//pictureBox1.Invalidate(); // don't do this here!
using (Graphics G = Graphics.FromImage(pictureBox1.Image))
foreach (ant a in ants)
{
c = Brushes.DarkBlue;
if (a.role == AntRole.Scout)
{
a.Move(i);
c = Brushes.Red;
}
// this draws onto the surface:
e.Graphics.FillRectangle(c, a.position.x, a.position.y, 1, 1);
// and this into the Image bitmap below:
G.FillRectangle(Brushes.Gray, a.position.x, a.position.y, 1, 1);
}
}
请注意,曲面位于图像上方
我不确定你的代码的细节;尤其是变量i
不清楚。。你可能想考虑浮动的位置…
不要从Paint
事件调用pictureBox1.Invalidate()
,因为这通常会再次触发Paint
事件。。相反,这可能会移动到动画计时器滴答声或按钮单击等
还要注意using
子句,它确保我创建的Graphics
对象被释放
本例假设您已经可以正确绘制蚂蚁本身,只需添加轨迹。使用矩形F而不是矩形。最后两个参数(1,1)是宽度和高度,它们是浮点数。使其变小,以便不过度写入旧点。创建位图并在其上绘制,而不是在绘制事件期间直接绘制到picturebox中。绘制过程不会在无效周期内保持像素不变。请勿从绘制事件或从绘制事件调用的事件调用pictureBox1.Invalidate()!因此,在移除无效和显示后,你应该看到你所有的蚂蚁,前提是它们的位置实际上是正确的。如果我正确地应用了你的解决方案假设,它会画出轨迹,但会同时出现。你也一样吗?我正在寻找的行为是重新绘制每一步。@sipronanceaaigor-在
单击事件中,我应用了for
循环来演示100条轨迹。删除这个循环。好的,我知道它是如何工作的,现在我已经能够正常运行它了。是否有某种通用处理程序可以避免单击或鼠标移动?我在想一个简单的循环,直到有一个线程退出。Sleep(amount)来减慢模拟OK,考虑到计时器,我可以问你另一个处理程序吗?抱歉,但我无法让它运行,我开始关注@alexander reply。“i”是完整源代码中的一个输入错误。在使alexander的代码正常工作后,我正在寻找您的代码,但它在第一次迭代中出现,我不知道如何使其正确运行。抱歉,这是我第一次在WinForms中使用图形。前两行是否运行一次?如何触发渲染器?从计时器开始。滴答声?它们只运行一次,但我没有触发任何东西。我原以为“Application.Run(new ShowAnts());”会在表单生命周期内一直循环主方法。嗯,不会。空闲时间内不会发生任何事情。如果你什么都不做,你的蚂蚁怎么移动???通常的方法是让计时器带有一个包含pictureBox1.Invalidate()的勾号事件代码>。。计时器的间隔可能为200毫秒,每秒触发滴答声5次。。