进度条上的文字超出范围

时间:2012-03-10 10:40:14

标签: c# winforms multithreading c#-4.0

即时通讯在进度条上写入一些文本时遇到一些问题,它会显示但是一旦GUI线程完成绘图就会消失,并且运行循环的单独线程会再次开始。我假设这是因为它超出范围,但我不知道如何解决它。

总体布局如下:

namespace namespace1
{
    public partial class Form1:Form
    {
     ....
    }

    public class ProgressBar
    {
        public void SubscribeToUpdateEvent()
        {
            //subscribe incrementPB to event
        }

        public void IncrementPB(object sender, EventArgs e)
        {
            //Update progress bar's value
            DrawPercentage(value);        
        }

        public void DrawPercentage(Value)
        {

        using (Graphics Draw = statusBar.CreateGraphics())
        {
            Draw.DrawString(percentage.ToString() + "%", ProgressBar.DefaultFont, Brushes.Black, new PointF((statusBar.Width / 2) - ((Draw.MeasureString(percentage.ToString() + "%", ProgressBar.DefaultFont)).Width / 2.0F),
                (statusBar.Height / 2) - ((Draw.MeasureString(percentage.ToString() + "%", ProgressBar.DefaultFont)).Height / 2.0F)));
        }
    }
}

//第二个文件,它在一个单独的线程上处理一堆数据,并在每次循环后引发事件。

namespace namespace2
{
    public class MyClass
    {
        public void iterator()
        {
            for(int i=0;i<10;i++)
            {
                //raise event to update the progress bar here
            }
        }
     }
 }

感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

当进度条上发生下一个Paint事件时,百分比标签可能会被删除。尝试将进度条实现为用户控件,这样您可以覆盖OnPaint方法并在那里呈现文本(在base.OnPaint(e)之后)。
我做了一些简单的课程来模拟你的情况。以下是适用于我的方法:

1)进度条控件(简单实现,只是为了概述OnPaint的基本思想):

public partial class CustomProgressBar : UserControl
{
    public int Percentage { get; set; }

    public CustomProgressBar()
    {
        InitializeComponent();
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        Graphics g = e.Graphics;
        Rectangle bounds = new Rectangle(ClientRectangle.X, ClientRectangle.Y, ClientRectangle.Width - 1, ClientRectangle.Height - 1);

        // Paint a green bar indicating the progress.
        g.FillRectangle
        (
            Brushes.LimeGreen,
            new Rectangle
            (
                bounds.X,
                bounds.Y,
                (int)(bounds.Width * Percentage / 100.0),
                bounds.Height
            )
        );

        // Draw a black frame around the progress bar.
        g.DrawRectangle(Pens.Black, bounds);

        // Draw the percentage label.
        TextRenderer.DrawText(g, Percentage + "%", Font, bounds, ForeColor);
    }
}

2)表示在后台线程中运行的作业的类:

public class BackgroundJob
{
    public event Action<object, int> StepCompleted;

    public void Execute()
    {
        const int TotalSteps = 10;
        for (int step = 1; step <= TotalSteps; step++)
        {
            // Execute some heavy work here.
            Thread.Sleep(1000);

            // Calculate percentage (0..100).
            int percentage = (int)(step * 100.0 / TotalSteps);

            // Notify the subscribers that the step has been completed.
            OnStepCompleted(percentage);
        }
    }

    protected virtual void OnStepCompleted(int percentage)
    {
        if (StepCompleted != null)
        {
            StepCompleted(this, percentage);
        }
    }
}

3)表格类。包含自定义进度条控件,并在按下按钮时启动后台作业。

public partial class MainForm : Form
{
    public MainForm()
    {
        InitializeComponent();
    }

    private void btnStartJob_Click(object sender, EventArgs e)
    {
        Thread backgroundThread = new Thread
        (
            () =>
            {
                var job = new BackgroundJob();
                job.StepCompleted += job_StepCompleted;
                job.Execute();
            }
        );
        backgroundThread.Start();
    }

    private void job_StepCompleted(object sender, int percentage)
    {
        progressBar.Percentage = percentage;

        // Force the progress bar to redraw itself.
        progressBar.Invalidate();
    }
}

你可以在内部调用Invalidate()(在Percentage属性设置器中),我单独调用它只是为了强调如何触发绘制过程。