【问题标题】:Windows forms: How to handle redrawing efficiently?Windows 窗体:如何有效地处理重绘?
【发布时间】:2010-01-16 00:25:50
【问题描述】:

我有一个带有图片框的表单,它显示图片和在图片框的 Paint 事件处理程序中绘制的一些叠加层。叠加层会根据鼠标移动更新其自身(基本上会改变叠加层不同部分的不透明度)。

目前,我正在从鼠标移动处理程序调用pictureBox.Invalidate() 以确保重新绘制覆盖。我还实现了一些逻辑来确定是否真的需要重新绘制 - 如果没有对象随着鼠标移动而改变其不透明度,PictureBox 不会失效。

当我移动鼠标的速度比非常慢时,我仍然在双核机器上获得 50% 的 CPU 使用率 - 我猜绘画例程无法像鼠标那样频繁地重新绘画生成移动的事件。

绘制的对象不多,最多 10 个填充矩形,每个矩形有 4 个填充三角形角。问题已经存在于单个覆盖对象中。基本上只有FillRectangleFillArea 方法用于执行绘画。

在这种情况下,您会提出什么方法来防止如此高的 CPU 使用率?

【问题讨论】:

  • 你的电脑是什么规格的?你有板载显存的显卡吗?
  • 没有板载显卡,这是一款带有游戏显卡的高端开发机器 - 不是最新一代,但绝对是一款不错的。

标签: c# winforms user-interface gdi+


【解决方案1】:

好吧,对于初学者来说,弄清楚您实际上需要多长时间重绘一次才能获得所需的效果。现在,您正在重绘以响应鼠标事件,但可能比您想象的要多很多,而且您可能不需要为每个事件重绘.绘制(响应 Invalidate())在大多数情况下是低优先级的,但这只是意味着你最终会用完任何空闲的 CPU 来完成它 - 最好你跟踪您上次重新粉刷的时间,避免过早重新粉刷。

使用计时器将刷新率固定在某个恒定值(从 40 毫秒延迟开始,大约 25hz 的刷新率,并根据需要增加或减少)是一种简单的方法...计时器 (System.Windows. Forms.Timer 至少)也是低优先级的,因此您不必担心刷新逻辑会抢占更重要的事件处理程序。

当然,保留您正在使用的现有代码以确定是否有任何实际更改。当它设置一个标志时,当该标志没有设置时,只需在你的计时器事件处理程序中什么都不做。

完成此操作后,您应该会看到使用的最大处理时间立即减少,因为您将刷新率与鼠标率分离。您还会发现您可以更好地控制中值处理时间,因为刷新率在您的控制之下:太高,降低计时器滴答率;不够流畅,加大吧!

【讨论】:

    【解决方案2】:

    限制绘制周期。

    例如,在游戏编程中,典型的帧速率是 30-60fps 或每秒 30 到 60 帧。这意味着屏幕每秒绘制 30-60 次。也对您的应用程序应用某种限制。 12fps 大约是人眼被欺骗认为是动画的最低帧率,所以我不会低于这个。

    说实话,鼠标移动似乎是错误的。例如,快速向鼠标发送垃圾邮件会提高绘制速率。

    【讨论】:

      【解决方案3】:

      如果您在鼠标移动事件中重绘,那么您将重绘很多。问题是,您真的需要在每次实际移动鼠标时绘制它,还是希望它在完成移动时绘制?或者介于两者之间?添加一些仅在鼠标移动结束时重绘的逻辑,或类似的效果。

      【讨论】:

      • 作为对鼠标移动的反应,我肯定需要重绘 - 有些区域会根据鼠标距离改变不透明度
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-12-02
      • 1970-01-01
      • 2010-10-09
      • 1970-01-01
      • 2019-09-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多