2
   private void AddMyScrollEventHandlers()
   {
       VScrollBar vScrollBar1 = new VScrollBar();
   }

   private void button1_Click(object sender, EventArgs e)
   {
       while (true)
       {
           if (vScrollBar1.Value + 1 < vScrollBar1.Maximum)
           {
               vScrollBar1.Value = vScrollBar1.Value + 1;    
               label1.Text = vScrollBar1.Value.ToString();                       
           }       
           else 
           {         
               break;      
           }

           System.Threading.Thread.Sleep(200);
       }
   }

   private void button2_Click(object sender, EventArgs e)
   {
       // vScrollBar1.Scroll
   }

我是 C# 新手。我正在研究滚动。我在这里想要的是,如果有人点击 button1 然后滚动自动移动到最后,我想在 label1 中显示渐变值。此外,当有人单击 button2 滚动停止时。

现在的问题是 label1 不显示值的渐变。它在滚动停止时显示一次值。

此外,当滚动继续时,即当循环工作时,我无法单击按钮 2。其实我什至不能点击表格。

有人请给我一些想法如何做到这一点。

4

3 回答 3

5

发生这种情况是因为执行任务的线程很忙,并且更新 UI 的线程是同一个线程。您可以使用多线程解决方案。看一眼 BackgroundWorker

于 2013-03-14T20:23:43.970 回答
1

所有的 UI 事件都在应用程序的主线程中运行,因此应用程序一次只能处理一个事件。当应用程序正在处理一个事件时,不会处理其他事件。

由于您定期进行与 UI 相关的工作,因此最好的选择是使用Timer该类:

  1. 从工具箱中拖放Timer到表单中。
  2. 在属性窗口中,将时间间隔设置为 200。
  3. 双击计时器对象以创建Tick事件处理程序。
  4. 将此代码放入新创建的timer1_Tick方法中:

     if (vScrollBar1.Value + 1 < vScrollBar1.Maximum)
     {
         vScrollBar1.Value = vScrollBar1.Value + 1;    
         label1.Text = vScrollBar1.Value.ToString();                       
     }       
     else 
     {         
         timer1.Stop();
     }
    
  5. 改变你的方法如下:

    private void AddMyScrollEventHandlers()
    {
        timer1.Start();
    }
    
    private void button2_Click(object sender, EventArgs e)
    {
        timer1.Stop();
    }
    

现在你完成了。

于 2013-03-14T20:26:50.023 回答
0

我建议使用BackgroundWorker控制,正如Agustin Meriles所建议的那样。但是,需要注意的更重要的一点是,您应该使用Control.Invoke(...)方法从另一个线程更新控件。

我已经修改了您的代码,在示例应用程序中对其进行了测试,它似乎可以正常工作。

首先,将一个新BackgroundWorker控件添加到您的表单并分配backgroundWorker1_DoWork给它的DoWork事件。

然后,您可以使用以下代码:

private void button1_Click(object sender, EventArgs e)
{
    //code from here is moved to BackgroundWorker control
    backgroundWorker1.RunWorkerAsync();
}

private void button2_Click(object sender, EventArgs e)
{

}

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    //while (true)
    //the condition directly in the while looks more clear to me
    while (vScrollBar1.Value + 1 < vScrollBar1.Maximum)
    {
        //update controls using Invoke method and anonymous functions
        vScrollBar1.Invoke((MethodInvoker)delegate() { vScrollBar1.Value += 1; });

        label1.Invoke((MethodInvoker)delegate() { label1.Text = vScrollBar1.Value.ToString(); });

        //when called inside BackgroundWorker, this sleeps the background thread, 
        //so UI should be responsive now
        System.Threading.Thread.Sleep(200);
    }
}

如果您在使用此代码时有任何问题,请告诉我。

更新

ProgressChanged如评论中所述,您还可以使用BackgroundWorker. 它需要对代码进行更多更改,但更适合这种情况。您可以在此处找到有关它的一些信息:http: //msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.progresschanged.aspx

如果您不打算在while循环中添加任何其他具有更多处理的代码,您也可以使用Timer控制,正如MD.Unicorn在他的回答中所建议的那样。

于 2013-03-14T20:41:40.040 回答