View()
{
InitializeComponent();
ViewModel vm = new ViewMode();
this.BindingContext= vm;
}
标有“1”的行在时间过程中执行得越来越慢。这是下面的“绘图”功能代码:
private void timer1_Tick(object sender, EventArgs e)
{
pictureBox1.Invalidate();
pictureBox1.Paint += new PaintEventHandler(Draw);//1
foreach (Line line in lines)//array "lines" contains just 16 objects
{
//calculating new coordinates ...
}
}
请你们告诉我,我该如何解决这个问题?谢谢!
答案 0 :(得分:1)
不要在timer1_Tick中执行pictureBox1.Paint + = new PaintEventHandler(Draw); // 1。在表单加载中执行一次。否则,每次Paint事件都会多次调用Draw(),调用次数也会增加。
答案 1 :(得分:1)
试试这个
private void timer1_Tick(object sender, EventArgs e)
{
Graphics g = pictureBox1.CreateGraphics();
foreach (Point line in lines)
{
g.DrawLine(new Pen(Brushes.Black, 5f), line.P1, line.P2);
g.FillEllipse(Brushes.Red, line.P1.X - 2.5f, line.P1.Y - 2.5f, 5, 5);
g.FillEllipse(Brushes.Red, line.P2.X - 2.5f, line.P2.Y - 2.5f, 5, 5);
g.DrawEllipse(new Pen(Brushes.Red, 5f), line.P1.X, line.P1.Y, 1, 1);
g.DrawEllipse(new Pen(Brushes.Red, 5f), line.P2.X, line.P2.Y, 1, 1);
}
}
如果它不显示效果,则在循环后添加以下行
pictureBox1.Invalidate();
答案 2 :(得分:1)
除了解决其他答案中已经指出的事件处理程序问题之外,我还会在代码中更改一些内容。
首先,为什么要创建这么多Pen
?把它们带出循环:
void Draw(object sender, PaintEventArgs e)
{
var blackPen = new Pen(Brushes.Black, 5f);
var redPen = new Pen(Brushes.Red, 5f);
foreach (Line line in lines)
{
e.Graphics.DrawLine(blackPen, line.P1, line.P2);
e.Graphics.FillEllipse(Brushes.Red, line.P1.X - 2.5f, line.P1.Y - 2.5f, 5, 5);
e.Graphics.FillEllipse(Brushes.Red, line.P2.X - 2.5f, line.P2.Y - 2.5f, 5, 5);
e.Graphics.DrawEllipse(redPen, line.P1.X, line.P1.Y, 1, 1);
e.Graphics.DrawEllipse(redPen, line.P2.X, line.P2.Y, 1, 1);
}
}
嗯,现在,请注意Pen
实施IDisposable
。养成处理完这些物品的习惯;这样,您将确定性地释放基础非托管资源,而不是GC
决定:
void Draw(object sender, PaintEventArgs e)
{
using (var blackPen = new Pen(Brushes.Black, 5f))
using (var redPen = new Pen(Brushes.Red, 5f))
{
foreach (Line line in lines)
{
e.Graphics.DrawLine(blackPen, line.P1, line.P2);
e.Graphics.FillEllipse(Brushes.Red, line.P1.X - 2.5f, line.P1.Y - 2.5f, 5, 5);
e.Graphics.FillEllipse(Brushes.Red, line.P2.X - 2.5f, line.P2.Y - 2.5f, 5, 5);
e.Graphics.DrawEllipse(redPen, line.P1.X, line.P1.Y, 1, 1);
e.Graphics.DrawEllipse(redPen, line.P2.X, line.P2.Y, 1, 1);
}
}
}
此外,您甚至可以考虑将Pen
缓存为实例变量;
class MyControl: ..., IDisposable
{
private readonly Pen blackPen = new Pen(Brushes.Black, 5f));
private readonly Pen redPen = new Pen(Brushes.Red, 5f));
void Draw(object sender, PaintEventArgs e)
{
foreach (Line line in lines)
{
e.Graphics.DrawLine(blackPen, line.P1, line.P2);
e.Graphics.FillEllipse(Brushes.Red, line.P1.X - 2.5f, line.P1.Y - 2.5f, 5, 5);
e.Graphics.FillEllipse(Brushes.Red, line.P2.X - 2.5f, line.P2.Y - 2.5f, 5, 5);
e.Graphics.DrawEllipse(redPen, line.P1.X, line.P1.Y, 1, 1);
e.Graphics.DrawEllipse(redPen, line.P2.X, line.P2.Y, 1, 1);
}
}
private void Dispose(bool disposing)
{
....
if (disposing)
{
....
blackPen.Dispose(;)
redPen.Dispose();
}
}
}
答案 3 :(得分:0)
看起来你的问题是pictureBox1.Paint += new PaintEventHandler(Draw);
所以当paint事件触发第一个滴答时它在第二个刻度上没有做任何事情它会在第500个刻度重新绘制一次它重新绘制499次
你需要做的是
private void configure()
{
pictureBox1.Paint += new PaintEventHandler(pictureBox1_OnPaint);
}
private void timer1_Tick(object sender, EventArgs e)
{
pictureBox1.Invalidate();
}
private void pictureBox1_OnPaint(object sender, PaintEventArgs e)
{
foreach (Line line in lines)//array "lines" contains just 16 objects
{
//calculating new coordinates ...
e.Graphics.DrawLine(new Pen(Brushes.Black, 5f), line.P1, line.P2);
e.Graphics.FillEllipse(Brushes.Red, line.P1.X - 2.5f, line.P1.Y - 2.5f, 5, 5);
e.Graphics.FillEllipse(Brushes.Red, line.P2.X - 2.5f, line.P2.Y - 2.5f, 5, 5);
e.Graphics.DrawEllipse(new Pen(Brushes.Red, 5f), line.P1.X, line.P1.Y, 1, 1);
e.Graphics.DrawEllipse(new Pen(Brushes.Red, 5f), line.P2.X, line.P2.Y, 1, 1);
}
}
更详细一点,因为您显然不了解事件处理程序的工作原理
pictureBox1.Paint += new PaintEventHandler(pictureBox1_OnPaint);
读取当绘制事件发生时我想让你每次调用该命令时调用pictureBox1_OnPaint,你将该方法调用的额外实例添加到你的程序中
pictureBox1.Paint += new PaintEventHandler(pictureBox1_OnPaint);
pictureBox1.Paint += new PaintEventHandler(pictureBox1_OnPaint);
说当Paint发生时你想要两次调用pictureBox1_OnPaint。它永远不会触发事件,调用Invalidate()
会触发事件。
所以你需要做的是初始化表单时(这可能是构造函数,初始化事件,如(Form.Load)或类似的地方告诉表单你希望它与paint事件做什么时它发生在
pictureBox1.Paint += new PaintEventHandler( action );
但只做一次
然后在你的计时器调用Invalidate
上,以便触发事件
因为每次paint事件触发时都会出现tick上的逻辑,那么你也可以将它添加到handers动作中,而不是通过行集合两次