Delphi 10.3.3
Many want to use a busy indicator to show the user there is a non visible process in operation. Usually when Delphi programmers try this the first time they notice the TAniIndicator doesn't rotate when they want it to. The problem is that the background process is in the same main form thread as the AniIndicator, which stops the AniIndicator from visibly moving.
In this example we download a file from the internet in the background while the Delphi TAniIndicator component is busy rotating.
The main issue is that the AniIndicator needs to be running in the main form thread and whatever long process you are doing in the background has to be running in another created thread. It wont work the other way around.
You can download the example code below. This example works the same on Windows, Android, IOS and MacOS.
unit MainUnit;
interface
uses
System.Types, System.Classes, FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.StdCtrls,
FMX.Layouts, System.Net.HttpClient, System.Net.HttpClientComponent, System.Net.URLClient,
FMX.Controls.Presentation, FMX.Objects;
type
TMainform = class(TForm)
LoadButton: TButton;
AniIndicator1: TAniIndicator;
Layout1: TLayout;
Layout2: TLayout;
Layout3: TLayout;
Image1: TImage;
NetHTTPClient1: TNetHTTPClient;
Layout4: TLayout;
ClearImageButton: TButton;
procedure LoadButtonClick(Sender: TObject);
procedure ClearImageButtonClick(Sender: TObject);
private
{ Private declarations }
procedure load_from_internet;
public
{ Public declarations }
end;
var
Mainform: TMainform;
implementation
{$R *.fmx}
uses
System.threading, system.uitypes;
procedure TMainform.ClearImageButtonClick(Sender: TObject);
begin
Image1.Bitmap.Clear(TAlphaColorRec.White);
end;
procedure TMainform.load_from_internet;
var
Task: ITask;
url: string;
begin
// turn on ani indicator
mainform.AniIndicator1.Enabled := True;
mainform.AniIndicator1.Visible := True;
Task := TTask.Create(
procedure
var
ms: tmemorystream;
resp: IHTTPResponse;
begin
// ***** do what you need to do in the thread
// while the aniindicator is running **********
NetHTTPClient1.UserAgent := 'Mozilla/5.0+(Windows+NT+10.0;+Win64;+x64;+rv:75.0)+Gecko/20100101+Firefox/75.0';
ms := tmemorystream.Create;
// some image file on internet
url := 'https://www.i-logic.com/kitten.jpg';
try
resp := NetHTTPClient1.Get(url, ms);
if TTask.CurrentTask.Status <> TTaskStatus.Canceled then
begin
TThread.Queue(TThread.CurrentThread,
procedure
begin
// ****** this is where it comes when the
// thread is finished *************
// we can work with the visual form components
ms.Position := 0;
// put the data into image1
try
if resp.StatusCode = 200 then // file was found
image1.Bitmap.LoadFromStream(ms);
finally
ms.Free;
// turn off aniindicator
mainform.AniIndicator1.Enabled := False;
mainform.AniIndicator1.Visible := False;
end;
end);
end;
except
// ****** error in get url *************
TThread.Queue(TThread.CurrentThread,
procedure
begin
ms.Free;
// turn off aniindicator
mainform.AniIndicator1.Enabled := False;
mainform.AniIndicator1.Visible := False;
end);
end;
end);
Task.Start;
end;
procedure TMainform.LoadButtonClick(Sender: TObject);
begin
load_from_internet;
end;
end.
**********************************************
The mainunit FMX file:
object Mainform: TMainform
Left = 0
Top = 0
Caption = 'AniIndicator'
ClientHeight = 480
ClientWidth = 258
FormFactor.Width = 320
FormFactor.Height = 480
FormFactor.Devices = [Desktop]
DesignerMasterStyle = 0
object Layout1: TLayout
Align = Top
Size.Width = 258.000000000000000000
Size.Height = 73.000000000000000000
Size.PlatformDefault = False
TabOrder = 1
object LoadButton: TButton
Align = Center
Size.Width = 195.000000000000000000
Size.Height = 35.000000000000000000
Size.PlatformDefault = False
TabOrder = 0
Text = 'Load From Internet'
OnClick = LoadButtonClick
end
end
object Layout2: TLayout
Align = Top
Position.Y = 73.000000000000000000
Size.Width = 258.000000000000000000
Size.Height = 76.000000000000000000
Size.PlatformDefault = False
TabOrder = 2
object AniIndicator1: TAniIndicator
Align = Center
Size.Width = 81.000000000000000000
Size.Height = 68.000000000000000000
Size.PlatformDefault = False
end
end
object Layout3: TLayout
Align = Top
Position.Y = 149.000000000000000000
Size.Width = 258.000000000000000000
Size.Height = 156.000000000000000000
Size.PlatformDefault = False
TabOrder = 3
object Image1: TImage
MultiResBitmap = <
item
end>
Align = Center
Size.Width = 185.000000000000000000
Size.Height = 117.000000000000000000
Size.PlatformDefault = False
end
end
object Layout4: TLayout
Align = Top
Position.Y = 305.000000000000000000
Size.Width = 258.000000000000000000
Size.Height = 80.000000000000000000
Size.PlatformDefault = False
TabOrder = 5
object ClearImageButton: TButton
Align = Center
Size.Width = 124.000000000000000000
Size.Height = 32.000000000000000000
Size.PlatformDefault = False
TabOrder = 0
Text = 'Clear Image'
OnClick = ClearImageButtonClick
end
end
object NetHTTPClient1: TNetHTTPClient
Asynchronous = False
ConnectionTimeout = 60000
ResponseTimeout = 60000
HandleRedirects = True
AllowCookies = True
UserAgent = 'Embarcadero URI Client/1.0'
Left = 92
Top = 200
end
end
**************************************
Source Code:
https://i-logic.com/ftp/AniInicatorCode.zip
Thanks, very usefull.
ReplyDeleteexcellent. please keep posting to your blog. highly useful stuff
ReplyDelete