Recent

Author Topic: How to create a progress bar dialog  (Read 3303 times)

maurobio

  • Hero Member
  • *****
  • Posts: 623
  • Ecology is everything.
    • GitHub
How to create a progress bar dialog
« on: October 12, 2021, 02:31:35 am »
Dear ALL,

I have been trying to understand and find a simple way of handling a dialog with a progress bar which can be shown to the user during a lengthy process and also allow the cancellation of said process by means of a cancel button.

For that, I have developed three alternatives:

  • A form dialog created at design time;
  • A function creating a dialog at runtime;
  • A built-in task dialog;

None of these is fully working, because I could not devise how to update the progress bar during the execution of a process. I am also not sure what would be the best alternative (although the dialog created at runtime seems to be more simple and versatile).

All of the above include a progress bar and a cancel button.

Could someone give me some hints and suggestions on how to put any (or all) of these alternatives to work properly?

My test code is attached.

Thanks in advance!

With best wishes,
UCSD Pascal / Burroughs 6700 / Master Control Program
Delphi 7.0 Personal Edition
Lazarus 2.0.12 - FPC 3.2.0 on GNU/Linux Mint 19.1, Lubuntu 18.04, Windows XP SP3, Windows 7 Professional, Windows 10 Home

Gustavo 'Gus' Carreno

  • Hero Member
  • *****
  • Posts: 1120
  • Professional amateur ;-P
Re: How to create a progress bar dialog
« Reply #1 on: October 12, 2021, 03:01:13 am »
Boas Maurobio,

Before I have a look at your code I'm gonna shoot my big opinionated mouth and say:
  • I hope you used Application.PrecessMessages after each update to TProgressBar.Position
  • I agree that the runtime solution is the best cuz it's re-usable code that can be called from anywhere

Now, to look at the code and then give you a fact based opinion :)

Grande abraço,
Gus
Lazarus 3.99(main) FPC 3.3.1(main) Ubuntu 23.10 64b Dark Theme
Lazarus 3.0.0(stable) FPC 3.2.2(stable) Ubuntu 23.10 64b Dark Theme
http://github.com/gcarreno

Gustavo 'Gus' Carreno

  • Hero Member
  • *****
  • Posts: 1120
  • Professional amateur ;-P
Re: How to create a progress bar dialog
« Reply #2 on: October 12, 2021, 03:37:03 am »
Boas Maurobia,

Quick solution for Unit1:

Code: Pascal  [Select][+][-]
  1. { A simple design-time dialog form }
  2.  
  3. unit Unit1;
  4.  
  5. {$mode objfpc}{$H+}
  6.  
  7. interface
  8.  
  9. uses
  10.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, ComCtrls;
  11.  
  12. type
  13.  
  14.   { TProgressDlg }
  15.  
  16.   TProgressDlg = class(TForm)
  17.     CancelButton: TButton;
  18.     LabelText: TLabel;
  19.     ProgressBar: TProgressBar;
  20.     procedure CancelButtonClick(Sender: TObject);
  21.     procedure FormActivate(Sender: TObject);
  22.     procedure FormCreate(Sender: TObject);
  23.   private
  24.  
  25.   public
  26.  
  27.   end;
  28.  
  29. var
  30.   ProgressDlg: TProgressDlg;
  31.  
  32. implementation
  33.  
  34. {$R *.lfm}
  35.  
  36. { TProgressDlg }
  37.  
  38. procedure TProgressDlg.CancelButtonClick(Sender: TObject);
  39. begin
  40.   Close;
  41. end;
  42.  
  43. procedure TProgressDlg.FormActivate(Sender: TObject);
  44. var
  45.   index: Integer;
  46. begin
  47.   OnActivate:= nil;
  48.   for index := ProgressBar.Min to ProgressBar.Max do
  49.   begin
  50.     ProgressBar.Position:= index;
  51.     Application.ProcessMessages;
  52.     Sleep(10);
  53.   end;
  54. end;
  55.  
  56. procedure TProgressDlg.FormCreate(Sender: TObject);
  57. begin
  58.   ProgressDlg.Caption := 'Import Contacts';
  59.   LabelText.Caption := 'Converting contact details';
  60. end;
  61.  
  62. end.

I wasn't aware of the existence of TTaskDialog, so I need a bit of time to investigate, learn and then I'll come back with something.

The button that triggers the function is probably not a solution cuz the way you did it, there aren't any Objects from which we can have a procedure of object that we can attach to the OnActivate event.
Maybe there's a way, but heck, that could be REALLY clunky and cludgy and I don't think I'm gonna go there.

The best way to do it is to create a from and design it, like Unit2, but DO NOT have it created at Runtime.
Then treat that form just like another component that you create at runtime and lastly, call ShowModal.

I'll be back with a TTaskDialog based solution if i can devise one :)

Grande abraço,
Gus
« Last Edit: October 12, 2021, 04:05:31 am by Gustavo 'Gus' Carreno »
Lazarus 3.99(main) FPC 3.3.1(main) Ubuntu 23.10 64b Dark Theme
Lazarus 3.0.0(stable) FPC 3.2.2(stable) Ubuntu 23.10 64b Dark Theme
http://github.com/gcarreno

Gustavo 'Gus' Carreno

  • Hero Member
  • *****
  • Posts: 1120
  • Professional amateur ;-P
Re: How to create a progress bar dialog
« Reply #3 on: October 12, 2021, 04:08:39 am »
Boas Maurobio,

Ok, I've had a very sideways, quick glance at the code, the actual source code that deals with TTaskDialog.

While, yes, there is this flag that mentions a Progress Bar and even one that mentions a Marquee Progress bar, I see no code to even CREATE a progress bar.
I think this is because this is a wrapper around the Task Dialog that was introduced in Windows Vista or the likes.
It seems that it's not fully implemented/ported when you use GTK2.

So if you want a solution for this, you'll have to ask someone that has a Windows environment by default.
Ain't gonna abuse wine to figure this one out.

And BTW, if it's Windows only, meh, not multiplatform in my view :P

Looks like Unit2 kinda thing is the way to go...

Grande abraço,
Gus
« Last Edit: October 12, 2021, 04:20:09 am by Gustavo 'Gus' Carreno »
Lazarus 3.99(main) FPC 3.3.1(main) Ubuntu 23.10 64b Dark Theme
Lazarus 3.0.0(stable) FPC 3.2.2(stable) Ubuntu 23.10 64b Dark Theme
http://github.com/gcarreno

maurobio

  • Hero Member
  • *****
  • Posts: 623
  • Ecology is everything.
    • GitHub
Re: How to create a progress bar dialog
« Reply #4 on: October 12, 2021, 01:07:18 pm »
Boas @Gus!!!

Thanks a lot for your much insightful replies, they were really helpful!

In the end, the simplest solution (a design time form dialog) seems indeed to be the best.

My idea of implementing a function creating a dialog at runtime was inspired by a ProgressDialog implemented in the PyQt/PySide Python bindings of the Qt C++ GUI library, but there it is implemented as a class with methods for updating the progress bar. Perhaps something like that could be implemented in FPC/Lazarus, but it would require much more work (as you have already pointed out).

Ans yes, the TTaskDialog is available in FPC/Lazarus but the implementation seems far from being complete as compared to that of Delphi. Anyway, I was in doubt it these 'task dialogs' were for Windows only -- in which case, they are definetely not for me, as I am interested only in fully multiplatform solutions!

Now, let me just ask a humble, but decisive, question: where am I supposed to put the code of my 'lengthy process' in the quick solution you suggested for my Unit1? As you may recall, I want to present the user that dialog with a progress bar during the execution of a processe (which the user can interrupt by means of the 'Cancel' button).

In fact, I have seen proposals (at Stackoverflow, for example) for implementing such dialogs with timers and threads but they seem all too esoteric (especially the thread-based ones) to be required perform such a simple task.

Again, thank you very much!

With best wishes,
UCSD Pascal / Burroughs 6700 / Master Control Program
Delphi 7.0 Personal Edition
Lazarus 2.0.12 - FPC 3.2.0 on GNU/Linux Mint 19.1, Lubuntu 18.04, Windows XP SP3, Windows 7 Professional, Windows 10 Home

jamie

  • Hero Member
  • *****
  • Posts: 6130
Re: How to create a progress bar dialog
« Reply #5 on: October 12, 2021, 02:05:14 pm »
Make the form a StayOnTop style, this way the it will return when you show it and your large process loop can call an update method in the form to update the bar and check for a status of a field in your form that gets set to false for example with a cancel button.

make sure you call the Application.ProcessMessages during your loop.
The only true wisdom is knowing you know nothing

maurobio

  • Hero Member
  • *****
  • Posts: 623
  • Ecology is everything.
    • GitHub
Re: How to create a progress bar dialog
« Reply #6 on: October 12, 2021, 02:10:47 pm »
Hi, @jamie!

Yes, thanks for the important tips about the StayOnTop property and the Application.ProcessMessages (that one is already being called inside the loop).

With best wishes,
UCSD Pascal / Burroughs 6700 / Master Control Program
Delphi 7.0 Personal Edition
Lazarus 2.0.12 - FPC 3.2.0 on GNU/Linux Mint 19.1, Lubuntu 18.04, Windows XP SP3, Windows 7 Professional, Windows 10 Home

Zvoni

  • Hero Member
  • *****
  • Posts: 2327
Re: How to create a progress bar dialog
« Reply #7 on: October 12, 2021, 03:07:48 pm »
If it's a really lengthy process i'd rather look to put that lengthy process into its own thread.
From there you can send out (at intervals?) a "signal" (Keyword: Synchronize) to your Form containing the Progressbar to update it with transmitted values.

The best example for something like this is the "CopyFile"-Progress-Window/Dialog everyone should be familiar with independent of OS
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: How to create a progress bar dialog
« Reply #8 on: October 12, 2021, 03:14:43 pm »
Given the single-threaded design of the  LCL (based on VCL) you have to find a reliable communication method between the process as it progresses and the dialog display.

The attached project shows one way you can go about it.

maurobio

  • Hero Member
  • *****
  • Posts: 623
  • Ecology is everything.
    • GitHub
Re: How to create a progress bar dialog
« Reply #9 on: October 12, 2021, 03:28:55 pm »
Hi, @howardpc!

Nice code, sir! Thanks a lot! I will have to think a little bit more on how I can adapt it to the requirements of my application, but it is really fine.

With best wishes,
UCSD Pascal / Burroughs 6700 / Master Control Program
Delphi 7.0 Personal Edition
Lazarus 2.0.12 - FPC 3.2.0 on GNU/Linux Mint 19.1, Lubuntu 18.04, Windows XP SP3, Windows 7 Professional, Windows 10 Home

Gustavo 'Gus' Carreno

  • Hero Member
  • *****
  • Posts: 1120
  • Professional amateur ;-P
Re: How to create a progress bar dialog
« Reply #10 on: October 12, 2021, 05:02:19 pm »
Hey Howard,

The attached project shows one way you can go about it.

Looking at how you implemented this, I quite like your style.

Have one small question though: Did you code this under Windows?

I ask this cuz both actions that should be obeyed with the checkboxes don't work on my Ubuntu 21.04 64b.
  • When you select the Auto-Close, the dialog does not auto-close.
  • When you select the Progress Bar with text, no text is shown.

Probably need to read deeper into your code for the auto-close, but I do remember having had some issue in the past while attempting to have Text on the progress bar and it was a GTK2 issue, so maybe not your fault :)

Cheer,
Gus
Lazarus 3.99(main) FPC 3.3.1(main) Ubuntu 23.10 64b Dark Theme
Lazarus 3.0.0(stable) FPC 3.2.2(stable) Ubuntu 23.10 64b Dark Theme
http://github.com/gcarreno

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: How to create a progress bar dialog
« Reply #11 on: October 12, 2021, 06:01:34 pm »
No, I tested this only on Linux, and have not tested on Windows.

The show text on progressbar property has no effect on Linuxes.

My implementation of Autoclose is rather hacky since it depends on the Position property reaching 100%, which (because of rounding issues) may not always get reported.
I think to have a fully reliable autoclose you would need to introduce an OnCompleted callback which the linked process would trigger at an unequivocal process completion moment. This would be more reliable than testing a Single (or Integer) progress value, which might get lost or held up in the message queue.

« Last Edit: October 12, 2021, 07:00:50 pm by howardpc »

maurobio

  • Hero Member
  • *****
  • Posts: 623
  • Ecology is everything.
    • GitHub
Re: How to create a progress bar dialog
« Reply #12 on: October 12, 2021, 06:09:31 pm »
Hi, @Gus, @howardpc!

I have tested the code under Windows 10 and it seems to work fine. It also seems to be easier to adapt to my own needs than I have thought at first.

Many thanks!

With best wishes,
UCSD Pascal / Burroughs 6700 / Master Control Program
Delphi 7.0 Personal Edition
Lazarus 2.0.12 - FPC 3.2.0 on GNU/Linux Mint 19.1, Lubuntu 18.04, Windows XP SP3, Windows 7 Professional, Windows 10 Home

 

TinyPortal © 2005-2018