views:

830

answers:

3

I'm trying to make a progress bar that starts at 0%, and takes 5 seconds to get to 100%. The progress bar will begin to go up as soon as Button1 is clicked. Any advice? I looked on Google, but that gave me nothing good on this sort of thing.

Also, at 0%, there should be a label that says "Waiting...", when the progress bar starts, it should go to "Working...", and when it's done, it should say "Done!".

+7  A: 

You can use a timer with interval 50 and firstly set enabled to false.

procedure TForm1.Button1Click(Sender: TObject);
begin
  timer1.Enabled := True;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
const
  cnt: integer = 1;
begin
  ProgressBar1.Position := cnt;
  if cnt = 1 then Label1.Caption := 'Waiting...'
  else if cnt = 100 then begin
    Label1.Caption := 'Done!';
    Timer1.Enabled := False;
  end else
    Label1.Caption := 'Working...';
  Inc(cnt);
end;
SimaWB
One problem with using timers is that there is no guarantee it will take 5 seconds (2.5 in your example btw). Most of the times it will be a very close match. In a stressfull environment, it could be of by a magnitude of seconds.
Lieven
@Lieven: You are right, but the influence of this can be minimized by a less dumb algorithm: don't count the timer ticks, but calculate the elapsed time since the start in the event handler. For higher message priority post a WM_USER each 100 ms from a background thread instead.
mghie
Yep. This isn't a perfect solution, but the basic idea is correct
Mason Wheeler
Ok, I tried your code, and I run into a few problems. On my form, I have a TButton, TProgressBar, TTimer, and a TLabel. I copy and pasted the code, but it says that "Timer does not contain a member 'Enabled'". Same goes with Tprogressbar.Position, and Label1.Caption. What could I be missing?
PuppyKevin
Which Delphi version are you using?
SimaWB
My Turbo Delphi application tells me that it uses Version 10 Delphi.
PuppyKevin
I'm not sure why you've the error. But in the error message you've Timer. What is Timer?Do you have Timer1: TTimer; in your Form class. And also check your label, progressbar and form names.
SimaWB
Under form class, I have ProgressBar1: TProgressBar;, Button1: TButton;,Timer1: TTimer;,Label1: TLabel;. The TProgressBar, TButton, TTimer, and TLabel also have a error, saying "Undeclared Identifier '<insert one of the four>'".
PuppyKevin
You will also need to add a {$J+} directive to allow the const cnt: integer = 1; to be modified. Better to use a field of the object (FCnt : integer) for this. Also need to set FCnt back to 1 before or after each run.
Gerry
A: 
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ExtCtrls, ComCtrls, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Label1: TLabel;
    ProgressBar1: TProgressBar;
    Timer1: TTimer;
    procedure Button1Click(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
begin
  Timer1.Enabled := True;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
const
  cnt: integer = 1;
begin
  ProgressBar1.Position := cnt;
  if cnt = 1 then Label1.Caption := 'Waiting...'
  else if cnt = 100 then begin
    Label1.Caption := 'Done!';
    Timer1.Enabled := False;
  end else
    Label1.Caption := 'Working...';
  Inc(cnt);
end;

end.
SimaWB
Thanks you for posting a fixed up code list for me! Now, when I try to run it, it says that Inc(cnt); Left side cannot be applied to.
PuppyKevin
The error is because you're trying to write to a const which by default can't be modified (thus a *constant*). Change it to var, and move it to above the declaration for TForm1.Timer1Timer() (outside the method itself); this allows changes and retains its value between calls to the timer event.
Ken White
Now I am confused. Should it be var Inc(cnt); above procedure TForm1.Timer1Timer(Sender: TObject);?
PuppyKevin
@Ken: Why would you advise to use a global variable instead of a member field?
mghie
@PuppyKevin: I use Delphi 5,6,7. And the code works fine. May be in your Delphi version, Gerry already said, you need to add a {$J+} directive to your unit file.
SimaWB
+3  A: 

Using GetTickCount() and intializing variables:

uses Windows;

var mseconds, starttime: integer;


procedore TForm1.FormCreate()
begin
  starttime := GetTickCount();
  mseconds := 0;
  Timer1.Enabled := false;
  Label1.Caption := '';
  ProgressBar1.Position := 0;
  Label1.Caption := 'Waiting...';
end;

procedure TForm1.Button1Click(Sender: TObject);
begin  
  ProgressBar1.Min := 0;
  ProgressBar.Max := 100;
  ProgressBar1.Position := 0;
  timer1.Enabled := True;
  Label1.Caption := 'Working...';  
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin  
  mseconds := GetTickCount() - starttime;
  if mseconds < 5000 then
    ProgressBar1.Position := Trunc(mseconds / 50)
  else begin
    ProgressBar1.Position := 100;
    Label1.Caption := 'Done!';
    Timer1.Enabled := false;
  end;
end;
eKek0
Ok. Your's had a few errors, but I am able to fix them up. For some reason though, when I hit the button, the label changes to Working..., but it does nothing else after that. I looked though to see if anything was wrong, could it be caused by: starttime := GetTickCount(); (read next comment)
PuppyKevin
and mseconds := starttime - GetTickCount();?
PuppyKevin
@PuppyKevin: You are on the right track; if you don't see the error then use the debugger, and you will find it. Also, Timer1 is not disabled when done...
mghie
I don't have Delphi installed anywhere, so I coded it in my head...
eKek0