当我调用一个函数并且它"运行"时(可能需要3秒钟 - 刷新函数从api服务器获取数据)我想将一个加载形式显示为Ajax加载指示器作为主窗体上方的叠加层.
我以前的尝试都失败了.我曾尝试更改在创建Main之后直接显示的Create the LoadingForm.然后我尝试了LoadingForm.Show/Showmodal.在模态序列中停止并且仅在我关闭表单时继续并且显示尽管窗口不关闭.
我也有这样的情况,表格打开但gif没有显示,应该是的地方只是白色并保持白色 - 没有图像没有动画
任何想法?
下面的代码使用一个线程模仿其Execute方法中的长时间运行块,并使用OnProgress"回调"来通知表单已完成的百分比已更改.
这是一个非常小的例子,但它可以告诉你我认为正确的方向之一.
请注意,当前未执行错误检查或异常处理.
Unit1.pas 主窗体和线程类
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.StdCtrls, Unit2;
type
TMyRun = class(TThread)
protected
procedure Execute; override;
public
OnProgress: TProgressEvent;
end;
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
FProgressForm: TfrmProgress;
procedure myRunProgress(Sender: TObject; Stage: TProgressStage;
PercentDone: Byte; RedrawNow: Boolean; const R: TRect; const Msg: string);
procedure myRunTerminate(Sender: TObject);
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TMyRun.Execute;
var
i: Integer;
r: TRect;
begin
for i := 1 to 100 do begin
if Terminated then
Break;
Sleep(50);//simulates some kind of operation
if Assigned(OnProgress) then
Synchronize(procedure
begin
OnProgress(Self, psRunning, i, False, r, '');
end);
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
FProgressForm := TfrmProgress.Create(nil);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
FProgressForm.Free;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
with TMyRun.Create do begin
FreeOnTerminate := True;
OnProgress := myRunProgress;
OnTerminate := myRunTerminate;
end;
FProgressForm.ShowModal;
end;
procedure TForm1.myRunProgress(Sender: TObject; Stage: TProgressStage;
PercentDone: Byte; RedrawNow: Boolean; const R: TRect; const Msg: string);
begin
FProgressForm.ProgressBar1.Position := PercentDone;
end;
procedure TForm1.myRunTerminate(Sender: TObject);
begin
FProgressForm.Close;
end;
end.
Run Code Online (Sandbox Code Playgroud)
Unit1.dfm
object Form1: TForm1
Left = 0
Top = 0
Caption = 'Form1'
ClientHeight = 81
ClientWidth = 181
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
Position = poDesktopCenter
OnCreate = FormCreate
OnDestroy = FormDestroy
PixelsPerInch = 96
TextHeight = 13
object Button1: TButton
Left = 48
Top = 24
Width = 91
Height = 25
Caption = 'Run the thread'
TabOrder = 0
OnClick = Button1Click
end
end
Run Code Online (Sandbox Code Playgroud)
Unit2.pas 进度对话框
unit Unit2;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ComCtrls;
type
TfrmProgress = class(TForm)
ProgressBar1: TProgressBar;
private
{ Private declarations }
public
{ Public declarations }
end;
var
frmProgress: TfrmProgress;
implementation
{$R *.dfm}
end.
Run Code Online (Sandbox Code Playgroud)
Unit2.dfm
object frmProgress: TfrmProgress
Left = 0
Top = 0
BorderStyle = bsSizeToolWin
Caption = 'frmProgress'
ClientHeight = 51
ClientWidth = 294
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
PixelsPerInch = 96
TextHeight = 13
object ProgressBar1: TProgressBar
Left = 16
Top = 16
Width = 265
Height = 17
TabOrder = 0
end
end
Run Code Online (Sandbox Code Playgroud)
请参阅注释,该注释指出长时间运行的操作需要访问主窗体中的网格,以避免阻止该对象上的VCL线程:
ShowModal返回后,使用编辑的数据副本更新网格.myRunProgress或在myRunTerminate方法中对于不同的用例,如果您的例程没有考虑已经更改的数据,那么混合方法也可能有意义(在构造函数中传递副本/在线程的同步块中更新网格):选择最适合您需求的方法.
如果另一个外部线程更新网格,a thread1可以读取数据,然后填写表单的私有队列 - 比如块中的一个TThreadList或另一个集合TCriticalSection- 并通知a thread2在队列上执行作业但我希望可能不需要这样做任务完成.
| 归档时间: |
|
| 查看次数: |
1966 次 |
| 最近记录: |