【问题标题】:Invalidate without OnPaint不使用 OnPaint 无效
【发布时间】:2015-08-15 14:45:38
【问题描述】:

我正在尝试在 Win Forms 中制作动画,我尝试了一种不同于在 timer_elapsed 处理程序中调用 Invalidate() 然后在 OnPaintHandler 中执行操作的方法。

我只是直接在pictureBox上绘制图像,然后当timer_ticks时,我调用Invalidate,然后在更新的位置手动重绘图像。

static void tmrMoving_Elapsed(object sender, EventArgs e, Train t)
{
    MainForm.playBox.Invalidate();

    g.DrawImage(t.components[i], new Rectangle(
                new Point(t.nextVagoonPositionX * 20, t.nextVagoonPositionY * 20), 
                new Size(20, 20)));
    t.nextVagoonPositionX += 1;
    t.nextPositionX = -1;
}

我有一个问题,当计时器滴答作响时,有时会绘制所需的图像,有时不会绘制,例如 30% 的机会不绘制(我有 1 秒的计时器间隔,所以我可以看到它),即使对象是移动或只是在同一个位置。

我尝试过的事情:

1.在 Invalidate() args 中设置一个区域 -> 图像在旧图像旁边被绘制了很多次(所以它没有在所需位置重新绘制,因为旧图像仍然在它们的位置)

2.在失效后调用 Update() 或 Refresh() 或两者兼而有之-> 没有显示任何图像

3. 将 Update() 或 Refresh() 或两者与 Invalidate(rectangulous region) 结合使用 -> 从未显示图像

4.设置DoubleBuffering true -> 无效

5. 摆弄 this.SetStyle(ControlStyles.UserPaint, true); -> 没有效果(甚至不确定它的作用。)

【问题讨论】:

  • 它确实被绘制了,只是不会持续很长时间。由 playBox 的普通 OnPaintBackground 和 OnPaint 方法覆盖。你是否能看到完全取决于你眨眼的频率以及 UI 线程的响应速度。线程竞赛错误的最终示例,您可以实际看到并且不必等待一周。你必须停止做错事。

标签: c# winforms animation graphics invalidation


【解决方案1】:

您不应该在 OnPaint 处理程序之外直接绘制 UI 控件。在“较低级别”的 WinAPI 中,您只需要在 WM_PAINT 上绘画到屏幕上,这就是引发 OnPaint 事件的原因。

将您的绘图代码 (g.DrawImage(...)) 从计时器处理程序中移出并移到 OnPaint 处理程序中。

【讨论】:

  • 谢谢您的信息,请问在处理 OnPaint 时谁是发件人?是那个计时器吗?
  • 不,最好是作为windows系统本身。出于所有目的,这发生在“幕后”。
  • 发件人是PictureBox,原因是系统还是你的代码
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-23
  • 2010-12-06
  • 1970-01-01
  • 2011-02-07
相关资源
最近更新 更多