当我调用一个函数并且它“运行”时(可能需要3秒钟 - 刷新函数从api服务器获取数据)我想将一个加载形式显示为Ajax加载指示器作为主窗体上方的叠加层。
我以前的尝试都失败了。我曾尝试更改在创建Main之后直接显示的Create the LoadingForm。然后我尝试了LoadingForm.Show/Showmodal。在模态序列中停止并且仅在我关闭窗体时继续并显示尽管窗口不关闭。
我也有这样的情况,表格被打开但是gif没有显示,应该是的地方只是白色并且保持白色 - 没有图像没有动画
任何想法?
答案 0 :(得分:9)
下面的代码使用一个线程模仿其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.
<强> 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
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.
<强> 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
参考注释,该注释指出长时间运行的操作需要访问主窗体中的网格,以避免阻止该对象上的VCL线程:
ShowModal
返回后,使用编辑后的数据副本更新网格。myRunProgress
或myRunTerminate
方法对于不同的用例,混合方法也可以有意义(在构造函数中传递副本/在线程的同步块中更新网格)如果你的例程没有考虑已经更改的数据:选择最适合您需求的方法。
如果另一个外部线程更新了网格,thread1
可以读取数据,然后填写表单的私有队列 - 比如TThreadList
或TCriticalSection
块中的其他集合 - 并通知thread2
在队列中执行作业,但我希望可能不需要这样做。
答案 1 :(得分:0)
创建对话框表单设置:
BorderIcons = []
BorderStyle = bsDialog
FormStyle = fsStayOnTop
Position = poScreenCenter
当您调用函数时,在主窗体中:
procedure TFormMain.Button1Click(Sender: TObject);
begin
Enabled:=false;
try
FormDialog.Show;
FormDialog.Refresh;
MyLongRunProcedure; // calls your procedure here
finally
Enabled:=true;
FormDialog.Close;
end;
end;
它应该有用..