我正在Delphi Tokyo中开发Firemonkey应用程序,并决定添加一个执行某些动画的加载器屏幕。我有一个带有列表动画的表单,该表单在一个线程中运行,然后我对datasnap服务器的调用在另一个线程中运行。我这样做是因为如果两个调用都不在线程中,则无法使动画正常工作。
现在在Windows版本上运行此程序可以正常工作。在我的华为手机和另一台三星平板电脑上运行它都可以在70%的时间内运行。其他30%的时间冻结,我必须终止该应用程序。完成数据快照加载后,应该释放并关闭加载程序窗体,并且将主面板的不透明度设置为1,然后再次启用该面板。我不确定100%是否冻结了应用程序以及代码是否未成功运行,那就应该再次启用面板。我能够在不工作的情况下进行一次调试,从而产生内存不足错误,但是在通过电话进行调试时无法重新创建问题。
这个想法是,当按下记录按钮时,加载程序屏幕会在检索数据时显示一些动画,然后再次将其隐藏。我在下面的代码中做错了吗?
ShowLoader;
fThread := TTask.Create
(
procedure ()
begin
try
LoDataset := fmxDataModule.ServerMethods.GetLoginDetails(edtEmail.Text, edtPassword.Text);
except on E:Exception do
begin
TThread.Synchronize(TThread.CurrentThread,
procedure()
begin
ShowMessage('The system could not log you in. Error Details: '+slinebreak+slinebreak+E.Message+slinebreak+slinebreak+'Please try again.');
HideLoader;
end
)
end;
end;
TThread.Synchronize(TThread.CurrentThread,
procedure()
begin
fmxDataModule.LoggedInUser.LoadFromDataset(LoDataset);
if fmxDataModule.LoggedInUser.CompanyID.Value > 0 then
begin
Toolbarheader.Visible := True;
lblLoginInfo.Visible := false;
lblWelcome.Text := 'Welcome ' + fmxDataModule.LoggedInUser.FirstName.Value + ', ' + fmxDataModule.LoggedInUser.LastName.Value;
GoToProfilesTab.Execute;
GenerateProfiles;
pnlButtons.Visible := True;
fLoggedIn := True;
FormResize(nil);
end else
begin
lblLoginInfo.Visible := True;
lblLoginInfo.Text := 'User does not exist, or login details invalid';
end;
end
);
HideLoader;
end
);
fThread.Start;
这是ShowLoader的代码:
procedure TfrmLogin.CreateLoaderForm;
begin
if Assigned(fLoader) then
FreeAndNil(fLoader);
fLoader := TfrmLoader.Create(Self);
floader.Parent := Self;
fLoader.Left := Self.Left + (Self.Width div 2) - (fLoader.Width div 2);
fLoader.Top := Self.Top + (Self.Height div 2) - (fLoader.Height div 2);
fLoader.Show;
end;
procedure TfrmLogin.ShowLoader;
begin
pnlMain.Enabled := false;
pnlMain.Opacity := 0.4;
TTask.Create (
procedure ()
begin
TThread.Queue(TThread.CurrentThread,
procedure()
begin
CreateLoaderForm
end);
end
).Start;
end;
隐藏装载程序:
procedure TfrmLogin.HideLoader;
begin
pnlMain.Enabled := True;
pnlMain.Opacity := 1;
// pnlMain.Repaint;
fLoader.Visible := False;
end;
我在上面的代码中缺少什么吗?
另一个问题是为什么我的表单没有在屏幕中间打开?我尝试了不同的方法,在表单属性中设置位置,然后手动进行计算。它总是在设备的左上角打开,但在Windows上可以使用。
答案 0 :(得分:1)
尝试了类似@nolaspeaker建议的其他方法,并同步了@RemyLebeau建议的用户名和密码字段之后,我删除了另一个线程中的表单加载器,问题仍然存在。这样做很明显,我最初发布的以下代码一定有问题,只是重构了一点:
TThread.CreateAnonymousThread
(
procedure
var
LsUsername,LsPassword:String;
begin
try
TThread.Synchronize(TThread.CurrentThread,
procedure()
begin
LsUsername := edtEmail.Text;
LsPassword := edtPassword.Text;
end
);
LoDataset := fmxDataModule.ServerMethods.GetLoginDetails(LsUsername, LsPassword);
except on E:Exception do
begin
TThread.Synchronize(TThread.CurrentThread,
procedure()
begin
ShowMessage('The system could not log you in. Error Details: '+slinebreak+slinebreak+E.Message+slinebreak+slinebreak+'Please try again.');
HideLoader;
end
)
end;
end;
TThread.Synchronize(TThread.CurrentThread,
procedure()
begin
fmxDataModule.LoggedInUser.LoadFromDataset(LoDataset);
if fmxDataModule.LoggedInUser.CompanyID.Value > 0 then
GoToProfilesTab.Execute
else
begin
lblLoginInfo.Visible := True;
lblLoginInfo.Text := 'User does not exist, or login details invalid';
end;
end
);
HideLoader;
end
).Start;
再尝试几次调试我在TTabControl.SetActiveTabWithTransition
中遇到的情况。
此行出现问题
LocalAnimateIntWait(Layout2, 'Position.X', Round(P.X), Duration, TAnimationType.In,
TInterpolationType.Linear);
在此代码块中:
procedure TTabControl.SetActiveTabWithTransition(const ATab: TTabItem; ATransition: TTabTransition;
const ADirection: TTabTransitionDirection = TTabTransitionDirection.Normal);
...
begin
case ATransition of
TTabTransition.Slide:
begin
FTransitionRunning := True;
ClipChildren := True;
try
...
if ADirection = TTabTransitionDirection.Normal then
begin
P...
end
else
begin
...
LocalAnimateIntWait(Layout2, 'Position.X', Round(P.X), Duration, TAnimationType.In,
TInterpolationType.Linear);
end;
finally
SetLength(FTransitionTabs, 0);
ClipChildren := False;
FTransitionRunning := False;
Realign;
end;
// Force repaint
Application.ProcessMessages;
end
else
ActiveTab := ATab;
end;
end;
因此,我删除了该单击的选项卡过渡,它最终按预期工作。在我将过渡放回Slide的那一刻,它再次冻结在该行上。我一定会报告此问题。