如何在 canvas 上快速重绘。 C# 窗体
How to redraw quickly on a canvas. C# WINFORM
对于我的软件,我使用的是 Systems.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(),都是先清屏)
非常感谢你帮助我。
Why is it faster???
出于最简单的原因:因为当您在 OnPaint()
方法中调用 Invalidate()
时,它会立即强制重新绘制 window ,这比计时器快得多。
.NET 中的计时器不适合高频操作。他们只保证间隔之间的时间 至少 您指定的时间。实际间隔可以而且通常比您指定的要长,尤其是当您使用非常短的间隔时(例如大约小于 10-20 毫秒)。这必然会限制您在使用计时器时重新绘制 window 的频率,其程度远高于仅尽可能快地重新绘制 window。
I would like to know if it exists a way for asking a controller to draw it surface without clearing it.
不容易,不。在最基本的级别,您可以重写 OnPaintBackground()
而不是调用基本实现。但是这种方法只有在您准备重绘所有内容时才有效,因为系统指望您在绘制时用正确的像素覆盖陈旧的像素。
事实上,一种更常见的方法是使用双缓冲。最基本的形式是在控件构造函数中设置 DoubleBuffered
属性。但是您也可以将不清除 window 与维护您自己绘制内容的屏幕外 Bitmap
对象结合起来。然后当 Paint
事件发生时,您只需将 Bitmap
复制到 window。
一种更复杂的方法涉及在 window 中托管 Direct2D
表面。不适合胆小的人,但应该在 Winforms 程序中提供最佳性能。
对于我的软件,我使用的是 Systems.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(),都是先清屏)
非常感谢你帮助我。
Why is it faster???
出于最简单的原因:因为当您在 OnPaint()
方法中调用 Invalidate()
时,它会立即强制重新绘制 window ,这比计时器快得多。
.NET 中的计时器不适合高频操作。他们只保证间隔之间的时间 至少 您指定的时间。实际间隔可以而且通常比您指定的要长,尤其是当您使用非常短的间隔时(例如大约小于 10-20 毫秒)。这必然会限制您在使用计时器时重新绘制 window 的频率,其程度远高于仅尽可能快地重新绘制 window。
I would like to know if it exists a way for asking a controller to draw it surface without clearing it.
不容易,不。在最基本的级别,您可以重写 OnPaintBackground()
而不是调用基本实现。但是这种方法只有在您准备重绘所有内容时才有效,因为系统指望您在绘制时用正确的像素覆盖陈旧的像素。
事实上,一种更常见的方法是使用双缓冲。最基本的形式是在控件构造函数中设置 DoubleBuffered
属性。但是您也可以将不清除 window 与维护您自己绘制内容的屏幕外 Bitmap
对象结合起来。然后当 Paint
事件发生时,您只需将 Bitmap
复制到 window。
一种更复杂的方法涉及在 window 中托管 Direct2D
表面。不适合胆小的人,但应该在 Winforms 程序中提供最佳性能。