我在下面的代码中以runtine创建了100多个矩形;
var
RectT: TRectangle;
MyThread: TThread;
Layout1: TLayout;
begin
MyThread := TThread.CreateAnonymousThread(procedure()
begin
TThread.Synchronize(nil, procedure()
var
z, i: integer;
begin
z := 0;
for i := 0 to 99 do
begin
RectT := TRectangle.Create(Self);
RectT.Name := 'Rectangle' + IntToStr(i);
RectT.Align := TAlignLayout.Top;
RectT.Margins.Top := 6;
RectT.Position.Y := z;
RectT.Height := 20;
RectT.Parent := Layout1;
if (i mod 10) = 0 then Layout1.UpdateEffects;
inc(z, 20);
end;
end);
end);
MyThread.FreeOnTerminate := True;
MyThread.Start;
端;
为什么在创建时不显示矩形,只在完成所有矩形的迭代时显示?
答案 0 :(得分:2)
首先,你需要在一个线程中移动for循环并在Synchronize调用中创建矩形,就像Deltics所做的那样。区别在于您不需要调用Repaint,并且需要使用currentthread来传递调用以进行同步。
试试这个(在按钮的OnClick事件中):
procedure TForm4.Button1Click(Sender: TObject);
begin
TThread.CreateAnonymousThread(procedure
var
I,z: Integer;
Total: Integer;
begin
Total := 0;
for I := 1 to 99 do
begin
TThread.Synchronize (TThread.CurrentThread,
procedure
var
RectT: TRectangle;
begin
RectT := TRectangle.Create(Self);
RectT.Name := 'Rectangle' + IntToStr(i);
RectT.Align := TAlignLayout.Top;
RectT.Margins.Top := 6;
RectT.Position.Y := z;
RectT.Height := 20;
RectT.Parent := Layout1;
Inc(z, 20);
end);
end;
end).Start;
end;
答案 1 :(得分:1)
如果此代码在主线程上运行(由于您没有提及任何线程,这似乎是这种情况),那么FMX运行时具有可视化更新UI的第一个机会就是您的代码本身跑完了。
如果您希望UI更新以在添加矩形时显示矩形,那么您需要重新编写它以使用允许UI有机会定期重新绘制的方法。
现在问题中的更新代码涉及一个帖子。但是,在您发布的代码中,您同步() 该线程中所有的工作。 同步 d代码在主线程中运行,因此同步所有工作的结果是删除线程的任何好处。
然而,你几乎就在那里。
对发布的代码进行小的更改,以便在线程中添加布局子对象,定期仅同步重新绘制布局对象本身,然后获得您正在寻找的结果:
var
MyThread: TThread;
begin
MyThread := TThread.CreateAnonymousThread
(
procedure()
var
z, i: integer;
RectT: TRectangle;
begin
z := 0;
for i := 0 to 999 do
begin
RectT := TRectangle.Create(Self);
RectT.Name := 'Rectangle' + IntToStr(i);
RectT.Align := TAlignLayout.Top;
RectT.Margins.Top := 6;
RectT.Position.Y := z;
RectT.Height := 20;
RectT.Parent := Layout1;
TThread.Synchronize(nil, procedure()
begin
Layout1.Repaint;
end);
inc(z, 20);
end;
end
);
MyThread.FreeOnTerminate := True;
MyThread.Start;
end;
我在 999 方法的演示中增加了子对象的数量,因为99不足以看到性能有任何明显变化。
正如所写,上面的代码也在添加了每个矩形之后重新绘制,但是这可以通过类似于发布的代码的方式轻松修改,以便仅在&#34之后重新绘制布局;批次"添加了矩形:
if (i mod 10) = 0 then
TThread.Synchronize(nil, procedure()
begin
Layout1.Repaint;
end);
这是一种简单的方法,解决了更新UI的直接问题,以显示使用这个非常简单的测试用例对该UI进行的一些后台更改的进度。在你的具体情况下,这是否真的是最合适的方法,你才能真正说出来。