【问题标题】:How to redraw quickly on a canvas. C# WINFORM如何在画布上快速重绘。 C# WINFORM
【发布时间】:2015-12-10 03:53:11
【问题描述】:

对于我的软件,我正在使用来自 Systems.timer 库的 Timer,每次我的计时器滴答作响时,它都会调用一个方法来重新绘制我的屏幕。我不想清除屏幕,然后重新绘制它。我只想直接在上面画出新的区域。

一开始,我是这样做的:

Constructor{
   ...
   this.timer = new Timer
   {
      Interval = 10,
   };
   this.timer.Elapsed += OnPaint;
   this.timer.start();
}

public void OnPaint(Object sender, EventArgs e)
{
   This.Parent.OnPaintLoadingCircle();
   This.Parent.OnPaintReadyToBePaintedAreas();
}

然后我注意到当 OnPaint 方法包含以下内容时,它的绘画速度要快得多:

public void OnPaint(Object sender, EventArgs e)
{
   This.Parent.Invalidate();
}

所以我有两个问题:

问题 1:

为什么更快???

因为当我调用 invalidate() 时:

  • UI 线程清屏。
  • 然后 UI 线程重绘旧区域
  • 然后UI线程绘制加载圆
  • 然后 UI 线程绘制新区域。

当我调用我的两个方法 OnPaintLoadingCircle() 和 OnPaintReadyToBePaintedArea() 时:

  • 定时器线程绘制加载圆
  • 然后定时器线程绘制新区域

问题 2:

我想知道它是否存在一种要求控制器在不清除它的情况下绘制表面的方法。 (我试过this.Parent.Update(),this.Parent.Refresh(),都是先清屏)。

非常感谢你帮助我。

【问题讨论】:

    标签: c# multithreading user-interface drawing


    【解决方案1】:

    为什么更快???

    出于最简单的原因:因为当您在 OnPaint() 方法中调用 Invalidate() 时,它会立即强制重新绘制窗口,这比计时器要快得多。

    .NET 中的计时器不适合高频操作。他们只保证间隔之间的时间至少是你指定的。实际间隔可以而且通常比您指定的要长,特别是如果您使用非常短的间隔(例如,小于 10-20 毫秒)。这必然会限制您在使用计时器时重新绘制窗口的频率,其程度远高于尽可能快地重新绘制窗口。

    我想知道是否存在一种要求控制器在不清除它的情况下绘制表面的方法。

    不容易,不。在最基本的层面上,您可以覆盖 OnPaintBackground() 并且不调用基本实现。但这种方法只有在您准备好重新绘制所有内容时才有效,因为系统会依靠您在绘制时用正确的像素覆盖陈旧的像素。

    事实上,更常见的方法是使用双缓冲。最基本的形式是在控件构造函数中设置DoubleBuffered 属性。但是您也可以将不清除窗口与维护自己的屏幕外Bitmap 对象相结合,您可以在其中绘制内容。然后当Paint 事件发生时,您只需将Bitmap 复制到窗口即可。

    更复杂的方法是在窗口中托管Direct2D 表面。不适合胆小的人,但应该在 Winforms 程序中提供最佳性能。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-04-26
      • 1970-01-01
      • 1970-01-01
      • 2013-11-06
      • 2011-08-16
      • 2020-10-10
      • 1970-01-01
      相关资源
      最近更新 更多