我的程序在其面板上绘制文字,但如果我想删除文本,我必须重新绘制。
如何手动调用(加注)绘画事件?
答案 0 :(得分:86)
在表单或控件的方法中,您有3个选择:
this.Invalidate(); // request a delayed Repaint by the normal MessageLoop system
this.Update(); // forces Repaint of invalidated area
this.Refresh(); // Combines Invalidate() and Update()
通常,您只需调用Invalidate()
并让系统将其与其他屏幕更新结合使用。如果你赶时间,你应该致电Refresh()
,但由于其他控件(特别是父母)无效,你会冒着连续几次重新粉刷的风险。
Windows(Win32和WinForms.Net)处理此问题的正常方法是等待MessageQueue运行为空,然后处理所有无效的屏幕区域。这是有效的,因为当某些变化通常会逐渐变为其他事物(控件)时也会发生变化。
Update()最常见的情况是在for循环中更改属性(例如,label1.Text,这将使Label无效)并且该循环暂时阻止消息循环。无论何时使用它,您都应该问自己是否应该使用线程。但答案并非总是如此。
答案 1 :(得分:42)
Invalidate()方法将导致重绘。
答案 2 :(得分:6)
我发现 Invalidate()创建了太多的闪烁。这是我的情况。我正在开发的自定义控件通过处理 Paint 事件来绘制其整个内容。
this.Paint += this.OnPaint;
此处理程序调用执行实际绘制的自定义例程。
private void OnPaint(object sender, PaintEventArgs e)
{
this.DrawFrame(e.Graphics);
}
模拟滚动我想在每次按下鼠标左键时光标移动时重新绘制控件。我的第一选择是使用 Invalidate(),如下所示。
private void RedrawFrame()
{
var r = new Rectangle(
0, 0, this.Width, this.Height);
this.Invalidate(r);
this.Update();
}
控件滚动正常,但闪烁远远超出任何舒适的等级。所以我决定在处理 MouseMove 事件后直接调用我的自定义 DrawFrame()方法,而不是重新绘制控件。这产生了平滑的滚动,没有闪烁。
private void RedrawFrame()
{
var g = Graphics.FromHwnd(this.Handle);
this.DrawFrame(g);
}
这种方法可能并不适用于所有情况,但到目前为止它很适合我。
答案 3 :(得分:5)
我想你也可以打电话给Refresh()
。
答案 4 :(得分:4)
调用control.invalidate并引发paint事件。
答案 5 :(得分:3)
刷新可能还会产生更易读的代码,具体取决于上下文。
答案 6 :(得分:2)
也许这是一个古老的问题,这就是为什么这些答案对我不起作用的原因...使用Visual Studio 2019,经过一些调查,这是我找到的解决方案:
this.InvokePaint(this, new PaintEventArgs(this.CreateGraphics(), this.DisplayRectangle));
答案 7 :(得分:0)
使用Control.InvokePaint
您也可以将其用于手动双缓冲