C#Winforms-ProgressBar无法正确显示和重置
我有一个windows桌面应用程序,我正在用visual basic中的windows窗体编写它。在这个应用程序中,我想显示一个简单的进度条,但我遇到了一个奇怪的问题。下面是更新进度条的简单for循环示例:C#Winforms-ProgressBar无法正确显示和重置,c#,.net,visual-studio,winforms,C#,.net,Visual Studio,Winforms,我有一个windows桌面应用程序,我正在用visual basic中的windows窗体编写它。在这个应用程序中,我想显示一个简单的进度条,但我遇到了一个奇怪的问题。下面是更新进度条的简单for循环示例: pBar.Visible = true; // pBar.Minimum and pBar.Step are both set to 1 using the properties pane in the design page pBar.Maximum = 100; for (int j =
pBar.Visible = true;
// pBar.Minimum and pBar.Step are both set to 1 using the properties pane in the design page
pBar.Maximum = 100;
for (int j = 0; j < 100; j++) {
double pow = Math.Pow(j, j); //Calculation
pBar.PerformStep();
}
pBar.Visible=true;
//使用设计页面中的属性窗格将pBar.Minimum和pBar.Step都设置为1
pBar.最大值=100;
对于(int j=0;j<100;j++){
双功率=数学功率(j,j);//计算
pBar.PerformStep();
}
上面的工作很好,但是,我希望能够重置进度条,以便稍后再次使用它。我假设我可以简单地在for循环之后设置pBar.Value=1
,但奇怪的是,这打破了进度条。该条不会像以前那样稳步增加,而是根本不会填充。如果我设置了pBar.Value=50
,则该条从中点开始,不会移动。它的行为类似于在for循环之前执行pBar.Value
,或者在每次循环迭代期间设置pBar.Value
(我已经确保没有将pBar.Value
语句错误地放在for循环中)
我认为发生这种情况的唯一原因是,C#异步运行我的for循环,并且立即设置值,然后由于某种原因它没有得到更新。我试着四处寻找答案,但到目前为止,我所找到的都是创建后台工作人员的方法(我对此不感兴趣),我重置进度条的方法应该是有效的
为什么会发生这种情况?使用计时器踏板来监视ProgressBar值是否达到最大值(100),然后在为真时将其重置为0。您还需要使用此小技巧绕过Win7\10。我只是做了一个简单的解释,可以帮助你更好地理解解决方案 以下是基于原始代码的完整代码
private void button1_Click(object sender, EventArgs e)
{
timer1.Enabled=true;
pBar.Visible = true;
pBar.Step = 1;
pBar.Minimum = 0;
pBar.Maximum = 100;
for (int j = 1; j < 101; j++)
{
// double pow = Math.Pow(j, j); //Calculation
pBar.Value = j;
pBar.Value = j-1;
pBar.PerformStep();
Thread.Sleep(20);
}
}
private void timer1_Tick(object sender, EventArgs e)
{
if (pBar.Value == 100)
{
pBar.Value = 0;
timer1.Enabled = false; // stop timer process
}
}
private void按钮1\u单击(对象发送者,事件参数e)
{
timer1.Enabled=true;
pBar.Visible=true;
pBar.Step=1;
pBar.最小值=0;
pBar.最大值=100;
对于(int j=1;j<101;j++)
{
//双功率=数学功率(j,j);//计算
pBar.值=j;
pBar.值=j-1;
pBar.PerformStep();
睡眠(20);
}
}
私有无效计时器1_刻度(对象发送方,事件参数e)
{
如果(pBar.Value==100)
{
pBar.值=0;
timer1.Enabled=false;//停止计时器进程
}
}
好的,下面是我试图回答你的问题:
我不认为在循环后将进度条的值重置为1时进度条不会“更新”。我认为整个进度条的动画都是假的
我查看了ProgressBar
的源代码。我们注意到,ProgressBar.Value
和ProgressBar.PerformStep
最终都会调用它,从而向底层本机控件发送消息。然后MSDN告诉我们,该条应该在每次收到此消息时重新绘制
然而,我怀疑这个控件在某种程度上虚拟了这个条的“真实”动画。我的猜测是,PBM_SETPOS
消息会立即被考虑到位置值(我们不希望我们的条每次都不知道它的值),但它们也必须被发送到某个队列以进行动画
动画可能会花费相当长的时间,如果发生需要停止或修改动画的事情,例如向后移动,动画将被取消。。。
假设您交替使用值1和51,而不是增加当前值,您希望看到哪种类型的动画
我通过替换pBar.PerformStep()模拟了这一点代码>在您的代码中:
pBar.Value=j%2*50+1;
当然,没有尾随的pBar.Value=1代码>
生成的动画不是令人恶心的1到51之间的往返,而是从1到51之间的干净平滑的过渡:)
我认为这证明了我的观点,即动画正在自己选择它想要的值,因此当快速在100之后设置1时,动画引擎决定不渲染任何内容
因此,如果要避免这种影响,最简单的方法是在使用进度条之前将其值重置为1,而不是在使用之后(顺便说一句,使用进度条时不假定进度条值为1,这可能是更好的编程实践)
PS:作为最后一点,同样的现象被用作在动画完成之前在进度条上强制一个高值的技巧
在您的情况下,您可以:
private void goslowyto100()=>pBar.Value=100;
私有的void GoQuicklyTo100()
{
pBar.最大值=101;
pBar.值=101;
pBar.最大值=100;
pBar.值=100;
}
希望这能回答你的问题
for循环后的pBar.Value=1会导致进度条不更新
可能控件未失效/更新导致绘制事件发生,请使用以下代码测试理论:
尝试:
C#
最好使用第二个线程来实现更平滑的显示,尽管单线程进度条是完全有效的
放入pBar.Invalidate()代码>在循环的最后应该回答您的问题,我想用一个您可能会涉及到的示例来说明为什么会发生这种情况
还请注意,有些人更喜欢使用更新:
使控件在其客户端区域内重新绘制无效区域
而不是使无效
:
使控件的整个表面无效,并使控件重新绘制
我在本例中使用后者对th的整个表面进行故障排除
for (int j = 0; j < 100; j++) {
...
}
pBar.Value = 1
pBar.Invalidate() //<-- cause a paint event
pBar.Value = j
If j Mod 5 = 0 Then pBar.Invalidate()
pBar.Value = j;
if (j % 5 == 0) pBar.Invalidate();