清除firemonkey应用程序中的VertScrollBox



我有一个适用于android手机的firemonkey应用程序,在XE7和Win8中。我有下面的过程ShowMsg,将消息显示到VertScrollBox中。

我想清除VertScrollBox,我正在尝试使用ClearVertScrollBox程序来完成,但我没有成功。

我在这里做错了什么?

procedure TForm1.ClearVertScrollBox;
var i:integer;
begin
for i:=VSB.ControlsCount-1 downto 0 do
begin
if (VSB.Controls[i] is TCalloutRectangle) then begin
VSB.Controls[i].DisposeOf;
VSB.Controls[i]:=nil;
end;
end;
VSB.Repaint;
end;
var VSB: TVertScrollBox;
procedure TForm1.ShowMsg(Title,GCMMsg,Msg:string);
var
CR: TCalloutRectangle;
L: TText;
begin
CR := TCalloutRectangle.Create(Self);
CR.Parent := VSB;
CR.Align := TAlignLayout.alTop;
CR.CalloutPosition := TCalloutPosition.cpLeft;
CR.Margins.Top := 10;
CR.Margins.Bottom := 10;
CR.Margins.Right := 5;
CR.Height := 75;
L := TText.Create(Self);
L.Parent := CR;
L.Align := TAlignLayout.alTop;
L.Text := Title;
L.Margins.Left := 15;
L.Margins.Right := 5;
L.Width := CR.Width-20;
L.Height:=20;
L := TText.Create(Self);
L.Parent := CR;
L.Align := TAlignLayout.alClient;
L.Text := GCMMsg;//GCMMsg+':'+Msg;
L.Margins.Left := 15;
L.Margins.Right := 5;
L.Width := CR.Width-20;
L.WordWrap := True;
L.AutoSize := True;
end;

您的ClearVertScrollBox只需要进行一些调整,您只需检查其控件并检查其中是否有一个是TCalloutRectangle,但TVertScrollBox不会简单地将您的TCalloutRectangle存储在第一个控制节点树中。

TVertScrollBox有一个TScrollContent,它将是您的控件存储的控件

这样的东西就足够了

var
I,II : Integer; 
begin
for i:= VSB.ControlsCount-1 downto 0 do
begin
if VSB.Controls[I].ClassType = TScrollContent then
begin
for II := VSB.Controls[I].ControlsCount-1 downto 0 do
begin
if VSB.Controls[I].Controls[II].ClassType = TCalloutRectangle then
begin
VSB.Controls[I].Controls[II].Parent := nil;
end;
end;
end;
end; 
end;

您还在创建TCalloutRectangle时创建内存泄漏

您正在与所有者一起创建所有对象,更具体地说,使用Self关键字,您将Form设置为所有者,因此,即使您从TVertScrollBox中"直观地"删除它,对象仍然归您的表单所有,对象引用计数永远不会达到0,这意味着ARC将无法释放它。

而不是像这样与所有者一起创建对象:

CR := TCalloutRectangle.Create(Self);

做这个

CR := TCalloutRectangle.Create(nil);

如果您已经将其分配给父对象,则不需要将其也分配给所有者,请为您的TCalloutRectangleTText(我假设它们是TLabels?)对象执行此操作

如果只使用父对象创建对象,并使用新代码将其从TVertScrollBox中删除,则会断开对这些对象的所有引用,这些对象就会被释放,这意味着不需要DisposeOf调用

我使用下面的代码来清除滚动框,在我的情况下,我只想删除列表中的所有项目,而不是特定的项目。

unit uScrollBoxHelper;
interface
uses FMX.Layouts;
type
TVertScrollBoxHelper = class helper for TVertScrollBox
public
procedure Clear;
end;
THorzScrollBoxHelper = class helper for THorzScrollBox
public
procedure Clear;
end;
implementation
{ TVertScrollBoxHelper }
procedure TVertScrollBoxHelper.Clear;
var
I: Integer;
begin
for I := self.Content.ChildrenCount - 1 downto 0 do
self.Content.Children.Items[I].DisposeOf;
end;
{ THorzScrollBoxHelper }
procedure THorzScrollBoxHelper.Clear;
var
I: Integer;
begin
for I := self.Content.ChildrenCount - 1 downto 0 do
self.Content.Children.Items[I].DisposeOf;
end;
end.

然后,当我想在表格中使用代码时,我只需执行以下操作:

VertScrollBox1.BeginUpdate;
VertScrollBox1.Clear;
...
VertScrollBox1.EndUpdate;

最新更新