C#Winform按钮 - >在进度条的某个阶段看不见的

时间:2015-11-18 17:35:18

标签: c# winforms

我正在为我打算创建的所有当前/未来程序制作加载工具。我制作了一个加载器和一个隐形按钮,我希望在某个阶段变为可见,但我无法弄清楚如何用我当前的代码实现它,如下所示:

<!-- ******************************************************** -->
<!-- The Grammar  configuration                               -->
<!-- ******************************************************** -->

<component name="jsgfGrammar" type="edu.cmu.sphinx.jsapi.JSGFGrammar">
    <property name="dictionary" value="dictionary"/>
    <property name="grammarLocation" 
         value="resource:/demo.sphinx.helloworld.elloWorld!/demo/sphinx/helloworld/"/>
    <property name="grammarName" value="hello"/>
<property name="logMath" value="logMath"/>
</component>

当我运行它时,button1.Visible = false; int i; progressBar1.Minimum = 0; progressBar1.Maximum = 231; // set to this "random" number because its the pixel length of the bar for (i = 0; i <= 220; i++) { progressBar1.Value = i; } if(progressBar1.Value == 220) //Stops BEFORE the end of the bar, to make the invisible button appear and make it possible to "skip" it { button1.Visible = true; } 已经处于值progressbar,我可以通过某种方式理解,因为没有任何&#34;步骤&#34;采取。但我不能完全确定我是否可以通过更改当前代码中的内容或更改代码来修复它。

2 个答案:

答案 0 :(得分:2)

如果没有a good, minimal, complete code example可靠地重现问题并显示您的确切方案,则无法确定最佳答案是什么。也就是说,如果我理解正确,你有:进度条;和一个按钮;以及一些过程,当它快要完成时,你想要显示按钮,当然还要继续更新进度。

Stack Overflow上有很多好的答案已经讨论了正确使用后台任务,异步方法和进度条,所以我不太喜欢这些点。但我会快速展示您的代码可能如何进行重组以实现您想要的目标。

让我们假设这一切都始于点击某个按钮(甚至可能是您设置为不可见的按钮)。然后我们可能重构上面的代码,可能出现在该按钮单击的事件处理程序中,看起来像这样:

private async void button1_Click(object sender, EventArgs e)
{
    button1.Visible = false;
    progressBar1.Minimum = 0;
    progressBar1.Maximum = 231;

    // Set up a callback that can be used to report progress on the UI thread
    Progress<int> progress = new Progress<int>(i =>
    {
        progressBar1.Value = i;
        if (progressBar1.Value == 220)
        {
            button1.Visible = true;
        }
    });

    // Perform your task; this will run in a different thread from the current,
    // UI thread, allowing the UI thread to do useful things like hiding the button
    // and updating the progress bar. Use of "await" here is what allows this
    // method to return, _temporarily_, so that the UI thread can continue to work
    await Task.Run(() =>
    {
        for (i = 0; i <= 220; i++)
        {
            // do NOT do this in real code...this is just here to represent _some_ kind
            // of time-consuming operation that justifies the use of the progress bar
            //in the first place
            Thread.Sleep(250);

            // Now report the progress value; the "progress" object will handle
            // marshaling back to the UI thread to call the anonymous method
            // declared above during the initialization of "progress"
            progress.Report(i);
        }
    });

    // Do any post-processing cleanup, UI updating, etc. here. This code
    // will execute only after the task started above has completed.
}


修改

根据OP的新要求,以上是上述版本,只有在完成所有处理后才能看到该按钮:

private async void button1_Click(object sender, EventArgs e)
{
    button1.Visible = false;
    progressBar1.Minimum = 0;
    progressBar1.Maximum = 231;

    // Set up a callback that can be used to report progress on the UI thread
    Progress<int> progress = new Progress<int>(i =>
    {
        progressBar1.Value = i;
    });

    // Perform your task; this will run in a different thread from the current,
    // UI thread, allowing the UI thread to do useful things like hiding the button
    // and updating the progress bar. Use of "await" here is what allows this
    // method to return, _temporarily_, so that the UI thread can continue to work
    await Task.Run(() =>
    {
        for (i = 0; i <= 220; i++)
        {
            // do NOT do this in real code...this is just here to represent _some_ kind
            // of time-consuming operation that justifies the use of the progress bar
            //in the first place
            Thread.Sleep(250);

            // Now report the progress value; the "progress" object will handle
            // marshaling back to the UI thread to call the anonymous method
            // declared above during the initialization of "progress"
            progress.Report(i);
        }
    });

    // Do any post-processing cleanup, UI updating, etc. here. This code
    // will execute only after the task started above has completed.

    button1.Visible = true;
}

答案 1 :(得分:0)

尽管我的问题很糟糕,但我能够让一些人真正了解它并帮助我开始使用它。我想要的是在我的进度条加载完成后会出现一个按钮,但我还没有找到最佳方法 - 我现在已经有了。

我的全部意图是创建一个Loader,我现在已经成功完成了。但是我已经拿出了不必要的&#34;部分只是回答我自己的问题。如果有人有兴趣,我很乐意发布它 - 我甚至可能会做一些建设性的批评,因为我是新的,只是这样做是为了满足我自己的好奇心。

    namespace RandomLoader
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

        bw.RunWorkerAsync();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        bw.WorkerReportsProgress = true;
        //The button was already made non-visible in my form's property window
    }

    private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        progressBar1.Value = e.ProgressPercentage;
        this.Text = e.ProgressPercentage.ToString() + " %"; // to make the form change name to the current progress of the Progress bar (I didnt want to make the text on top of the progress bar)
    }

    private void bw_DoWork(object sender, DoWorkEventArgs e)
    {
        for (int i = 1; i <= 100; i++)
        {
            Thread.Sleep(#); // to make the progress bar look realistic, so it had tiny stops and stuttering, like an actually functioning download bar does.wasnt instantly at 100% (I used 100 as in 1/10th of a second stutters before the bw would update the bar)
            bw.ReportProgress(i); // report progress from the background worker
        }
    }

    private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) // Once my bar is done loading I want it to sleep for just a tiny bit, because the background worker is done before the visualization on the progressbar is done.
    {
        Thread.Sleep(#);
        button1.Visible = true;
        this.Text = "Done Loading"; //Instead of making a convertion from string to int in my ProgressChanged event, I simply made it so that once it was done, it would say "done loading" rather than the current %
    }

    private void button1_Click(object sender, EventArgs e) // As this was a loader for my next few programs, I want it to open my not yet finished program, so an empty form will suffice as an example.
    {
        Form2 f2 = new Form2();
        f2.Show();
    }
}

我相信这与我的问题有关,但我可能错误地拿出了一些东西。