为什么Windows窗体控件的属性不能在OnPaint事件期间更改?
本文关键字:事件 OnPaint 窗体 Windows 控件 不能 属性 为什么 | 更新日期: 2023-09-27 18:09:13
我使用OnPaint (c#)事件在我的窗体中绘制一些东西。我想在OnPaint过程中获得变量的值。但是我不能得到它,只有在OnPaint过程之前或之后…
实际上,这个变量就像一个计数器,我想要得到它来增加ProgressBar的值。
我试着添加一个线程,一个定时器和"ValueChanged"事件,我仍然无法获得值。代码相当长(用于从一些数据生成热图)。
我在事件期间增加了一些for循环的值,并通过"Invalidate()"函数调用OnPaint事件。
我希望不要粘贴我的代码(它很长)!谢谢。
(简化)public partial class HeatPainter : UserControl
{
public long _progress = 0; //My counter
public HeatPainter()
{
InitializeComponent();
}
public void DrawHeatMap(List<List<int>> Items, decimal Value, int MaxStacks, int Factor, string FileName)
{
if (_allowPaint) //If the control is ready to process
{
timer1.Start();
_progress = 0;
_allowPaint = false;
Invalidate();
}
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
for (int Pass = _factor; Pass >= 0; Pass--)
{
//Some draw stuff
//...
_progress++;
}
}
private void timer1_Tick(object sender, EventArgs e)
{
Console.WriteLine(_progress);
}
}
看起来你的重新粉刷花了很多时间。在重新绘制期间,您无法更改表单上的任何内容(直到最后才会更改)。
所以你应该从另一个角度来看这个任务。如果您将在并行线程(或另一个并行化结构http://www.dotnetperls.com/backgroundworker)中创建图像(如如何使用。net在内存中动态创建jpg图像?)绘制完成后,将其设置为背景或某些PictureBox的.Image
。表单将一直响应。
你将不得不同步(更新你的进度条),但这并不是一个困难的任务(线程不更新进度条控件- c#, c# Windows窗体应用程序-从另一个线程和类更新GUI ?)。
对于未来:线程和后台工作者正在慢慢远离。网络世界。它们仍然在。net <中使用。但是。net 4.0及更高版本为异步操作提供了更好的抽象。我建议你阅读task和Async Await。它们更适合于许多"启动-工作-完成-结果"的场景。
你应该只使用一个异步构造(例如BackgroundWorker)来绘制图像。您的用户控件应该提供一个事件(实际上最好在用户界面之外重构此功能),例如
public event EventHandler ProgressChanged;
,并在修改Progress
的属性时在创建图像的代码中引发此事件。只是不要忘记同步和调度(见上文)。