我有一个适用于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);
如果您已经将其分配给父对象,则不需要将其也分配给所有者,请为您的TCalloutRectangle
和TText
(我假设它们是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;