Updating status label and status bar

K

K Viltersten

I added a status label and a status bar
and as the status reaches its maximum
the text on the label will change. The
problem is that the text changes BEFORE
the bar gets "pumped up" to the max.

bar.PerformStep ();
if (bar.Value < bar.Maximum)
status.Text = "Pretending to work!";
else
status.Text = "Done.";

The way i see it, it should first go
to the max and as the user gets to see
that the bar is full, the status text
is changed. Hints?
 
P

Peter Duniho

I added a status label and a status bar and as the status reaches its
maximum the text on the label will change. The
problem is that the text changes BEFORE
the bar gets "pumped up" to the max.

When you write "status bar", do you really mean the ProgressBar class?

From the code you posted, it seems that you do. But even so, you really
should get into the habit of being very specific about what you're doing.
There is in fact a concept of a "status bar", and it's entirely different
from that of the ProgressBar class (it's a small area at the bottom of the
window that displays status...see the StatusBar and ToolStripStatusLabel
classes for details).

As far as your specific question goes, the code snippet you posted should,
assuming the rest of the code doesn't do anything odd, do exactly what
you'd expect: set the text to "Done." at the same time that the progress
bar reaches its maximum value.

If this isn't what you're seeing, then it seems likely that somewhere in
the rest of the code is something that does something odd, resulting in
the text being updated before the progress bar is.

However, since you didn't post a concise-but-complete sample of code that
reliably demonstrates the problem, it's not nearly as likely that anyone
can answer your question.

Pete
 
F

Family Tree Mike

If you want to see the value at 100% before the text saying done shows up,
then you need to put a small delay in the "else" part of your code.
 
K

K Viltersten

bar.PerformStep ();
If you want to see the value at 100% before the text saying
done shows up, then you need to put a small delay in the
"else" part of your code.

I noticed that there's a property for the bar stating what time
it should take for the animation to move the fill to the
requested spot. I'm guessing that's the time i should delay
my text updating by. Correct?

When you mentioned a delay - is there an other way to do
it than threads? I've found this solution.

else {
System.Threading.Thread.Sleep (1000);
status.Text = "Done."; }

The thing is that while it postpones the text update (good,
good) it also removes the animation of the bar. By other
words - the bar waits for a second, then skips to the new
position, instead of being "pumped-up".

Most of all, it would be nice to get a report from the bar
saying "yey, i'm done animating" and then proceede.
Too much?
 
K

K Viltersten

I added a status label and a status bar and as the status
When you write "status bar", do you really mean the ProgressBar
class?

Yes. My bad. I'm referring to a green bar at the bottom of the
screen, right on an instance of the ToolsStrip class.
As far as your specific question goes, the code snippet you
posted should, assuming the rest of the code doesn't do anything
odd, do exactly what you'd expect: set the text to "Done." at the
same time that the progress bar reaches its maximum value.

After an investigation i learned that the animated move of the bar
starts and WHILE it's being "pumped-up", (in its own thread, i'd
guess), the program continues updating the label. So, odd - no.
But sure ugly and inconvienient...
If this isn't what you're seeing, then it seems likely that somewhere
in the rest of the code is something that does something odd,
resulting in the text being updated before the progress bar is.

I've tested creating a new, standard project with only this bar
being "pumped-up" as a single button is being pressed. Not
much of other code to interviene there.
However, since you didn't post a concise-but-complete sample
of code that reliably demonstrates the problem, it's not nearly
as likely that anyone can answer your question.

You surely don't refer to all the code being created, do you? VS
created at least three files for me, this far, i think. Did i
misunderstand something?
 
P

Peter Duniho

Yes. My bad. I'm referring to a green bar at the bottom of the screen,
right on an instance of the ToolsStrip class.


After an investigation i learned that the animated move of the bar
starts and WHILE it's being "pumped-up", (in its own thread, i'd
guess), the program continues updating the label. So, odd - no.
But sure ugly and inconvienient...

Okay, that makes sense. I haven't used ProgressBar enough to know the
specifics, but from your description it seems reasonable to believe that
it animates between settings. I'd never noticed that before, even when
the value changes dramatically, but I may just not have been paying
attention.

I don't know if there's a way to bypass the behavior. I can think of an
ugly hack though: create a different progress bar, already set to the
maximum value, that remains hidden until the end. Then when you reach the
end, swap it for the "live" one. :)

Personally, I'd live with the animation. But I know how it can feel
sometimes when the GUI just isn't doing _exactly_ what you want it to.
I've tested creating a new, standard project with only this bar being
"pumped-up" as a single button is being pressed. Not
much of other code to interviene there.

Okay. That's why I wrote "likely" as opposed to "must be". :)
You surely don't refer to all the code being created, do you? VS
created at least three files for me, this far, i think. Did i
misunderstand something?

The minimal VS Designer template is generally Program.cs, Form1.cs, and
Form1.Designer.cs, yes. In the simplest cases, sometimes you can post
only the code in Form1.cs, as long as everything else is obvious. This is
in fact worth a first try, usually, since it produces the least amount of
posted code.

But yes, if you want people to be able to actually execute the same exact
code you're executing and thus help you work through what's going on, you
need to post everything.

Note that you can take those three files and merge them into a single one
(editing to remove extra "using" namespace declarations and breaks between
the "partial" Form1 class, of course, so that it call compiles). A person
won't be able to modify something like that in the designer, but it's
easier to get it up and working to start with and otherwise is just as
helpful.

Pete
 
P

Peter Duniho

I noticed that there's a property for the bar stating what time
it should take for the animation to move the fill to the requested spot.

What property are you referring to? If you're talking about the
ProgressBar.MarqueeAnimationSpeed property, I believe that applies only to
the marquee-style progress bar. That is, the one that just has the blocks
animating across the bar over and over, rather than reflecting actual
progress.
I'm guessing that's the time i should delay
my text updating by. Correct?

I don't think that property would be useful in this case at all. But you
could try it and see. I would try setting it to 0; if it has any effect
on a non-marquee progress bar, maybe that would make the animation go away
entirely.

But again, from the docs anyway, it doesn't look like that'd actually have
any effect for a non-marquee progress bar.
When you mentioned a delay - is there an other way to do
it than threads? I've found this solution.

else {
System.Threading.Thread.Sleep (1000);
status.Text = "Done."; }

The thing is that while it postpones the text update (good, good) it
also removes the animation of the bar. By other
words - the bar waits for a second, then skips to the new
position, instead of being "pumped-up".

Instead of blocking your thread with the Sleep() method, you could
(should, IMHO) instead use a timer or background thread. For example:

System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();

timer.Interval = 1000;
timer.Tick += delegate(object sender, EventArgs e) { status.Text =
"Done"; timer.Stop(); };
timer.Start();

Or:

BackgroundWorker bw = new BackgroundWorker();

bw.DoWork += delegate(object sender, DoWorkEventArgs e)
{ Thread.Sleep(1000); };
bw.RunWorkerCompleted += delegate(object sender,
RunWorkerCompletedEventArgs e) { status.Text = "Done"; }
bw.RunWorkerAsync();

I don't really recommend the latter, as I think it's not a great idea to
block arbitrarily in thread pool threads (and should be avoided in any
thread, for that matter). I also think the latter isn't quite as nice
just in terms of how it's put together.

But with the delay only being 1 second, it's probably not that big of a
problem if you really really wanted to.

I'd use the Timer solution though.

Either of the solutions would allow the text to not be updated until
later, while still allowing the progress bar to do the animation it wants
to do.
Most of all, it would be nice to get a report from the bar saying "yey,
i'm done animating" and then proceede.
Too much?

No, not too much. I think that given that the bar animates, it would be
nice to either have control over the animation, or to be able to receive
updates regarding the status of the animation.

But as far as I know, neither of those are options. So if you really
don't want the text updated until the progress bar has had a chance to
visually reach the end, you're stuck with hacks such as the above. If
you're going to do a hack though, at least try to make it as friendly as
possible. Blocking the GUI thread for a full second isn't very friendly..

Pete
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top