为什么在OnPaint事件期间无法更改Windows窗体控件的属性

时间:2014-06-18 13:18:23

标签: c# events onpaint

我使用OnPaint(c#)事件在我的表单中绘制一些东西。我想在OnPaint过程中获取变量的值。但我不能在OnPaint过程之前或之后得到它......

实际上,变量就像一个我希望增加ProgressBar值的计数器。

我尝试添加一个Thread,一个Timer和“ValueChanged”事件,我仍然无法获得该值。 代码很长(用于从某些数据生成HeatMap)。

我在事件期间增加了一些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);
    }
}

1 个答案:

答案 0 :(得分:0)

看起来你的重新粉刷需要花费很多时间。在重新绘制过程中,您无法更改表单上的任何内容(直到结束时才会更改)。

所以你应该从其他角度看待这个任务。如果要在并行线程(或其他并行化构造How to create a jpg image dynamically in memory with .NET?)中创建图像(如http://www.dotnetperls.com/backgroundworker),该怎么办?绘制完成后,您将其设置为背景或某些PictureBox.Image。表格将始终响应。

您必须同步(更新进度条),但这不是一项艰巨的任务(Thread not updating progress bar control - C#C# Windows Forms Application - Updating GUI from another thread AND class?)。

对于未来:Threads和BackgroundWorkers正逐渐远离.NET世界。它们仍然在.NET中使用&lt; 4.0但.NET 4.0及更高版本为异步操作提供了更好的抽象。我建议您阅读TasksAsync Await。它们更适合于许多启动 - 工作 - 获得结果完成情景。

您应该只使用一个将绘制图像的异步构造(例如BackgroundWorker)。您的用户控件应该提供一个事件(实际上最好从用户界面重构此功能),如

public event EventHandler ProgressChanged;

并在修改Progress的属性时在创建图像的代码中引发此事件。只是不要忘记同步和调度(见上文)。