从 TGridPanel 中删除控件
Removing controls from a TGridPanel
我正在使用 TGridPanel 来管理多个面板。我创建面板并使用如下代码将它们添加到 GridPanel:
var
pnl: TPanel;
begin
pnl := TPanel.Create(GridPanel2);
pnl.Caption := 'Panel One';
pnl.Tag := 1;
pnl.Parent := GridPanel2;
pnl.Name := 'pnlOne';
GridPanel2.ControlCollection.AddControl(pnl);
pnl := TPanel.Create(GridPanel2);
pnl.Caption := 'Panel Two';
pnl.Tag := 2;
pnl.Parent := GridPanel2;
pnl.Name := 'pnlTwo';
GridPanel2.ControlCollection.AddControl(pnl);
pnl := TPanel.Create(GridPanel2);
pnl.Caption := 'Panel Three';
pnl.Tag := 3;
pnl.Parent := GridPanel2;
pnl.Name := 'pnlThree';
GridPanel2.ControlCollection.AddControl(pnl);
end;
您会注意到每个面板都有不同的标签值。
我想根据面板标签 属性 中的值从 GridPanel 中删除面板。我试过以下代码:
var
ii: integer ;
pnl: TPanel;
begin
for ii := 0 to GridPanel2.ControlCollection.Count -1 do begin
if GridPanel2.ControlCollection[ii].Control.Tag = 1 then begin
pnl := GridPanel2.ControlCollection[ii].Control as TPanel;
GridPanel2.ControlCollection.RemoveControl(pnl);
freeandnil(pnl);
end;
end;
gridpanel2.Refresh();
end;
如果该面板是集合中的最后一个面板,则效果很好。如果我尝试删除带有 tag = 1 或 tag = 2 的面板,我会收到超出范围的错误。在调试器中单击 "continue" 会在删除的面板所在的位置留下 space,因此删除面板。
我想看到的是,假设面板 2 被移除,随后的面板移动到一个位置以不留空隙。
我该怎么做?
如果重要的话,我正在使用 Delphi 10.1 Berlin。
与往常一样,从列表或集合中删除项目时,您需要在计数发生变化时采取预防措施。 for 循环计数在循环开始时确定。现在,如果您从列表中删除一个项目,当 for 循环持续到结束时,您将命中一个不存在的索引。
您可以通过多种方式避免这种情况,f.ex。找到并删除该项目后,通过跳出循环。
freeandnil(pnl);
break;
另一种方法,是运行 for 循环向后
for ii := GridPanel2.ControlCollection.Count -1 downto 0 do begin
或者您可以使用 Repeat Until
或 While
循环检查条件以在循环的每一圈继续。
要在删除项目后更新网格面板,请调用
中的一个或两个
gridpanel2.UpdateControlsRow();
gridPanel2.UpdateControlsColumn();
不过,要弄对顺序感觉还是挺棘手的
我正在使用 TGridPanel 来管理多个面板。我创建面板并使用如下代码将它们添加到 GridPanel:
var
pnl: TPanel;
begin
pnl := TPanel.Create(GridPanel2);
pnl.Caption := 'Panel One';
pnl.Tag := 1;
pnl.Parent := GridPanel2;
pnl.Name := 'pnlOne';
GridPanel2.ControlCollection.AddControl(pnl);
pnl := TPanel.Create(GridPanel2);
pnl.Caption := 'Panel Two';
pnl.Tag := 2;
pnl.Parent := GridPanel2;
pnl.Name := 'pnlTwo';
GridPanel2.ControlCollection.AddControl(pnl);
pnl := TPanel.Create(GridPanel2);
pnl.Caption := 'Panel Three';
pnl.Tag := 3;
pnl.Parent := GridPanel2;
pnl.Name := 'pnlThree';
GridPanel2.ControlCollection.AddControl(pnl);
end;
您会注意到每个面板都有不同的标签值。
我想根据面板标签 属性 中的值从 GridPanel 中删除面板。我试过以下代码:
var
ii: integer ;
pnl: TPanel;
begin
for ii := 0 to GridPanel2.ControlCollection.Count -1 do begin
if GridPanel2.ControlCollection[ii].Control.Tag = 1 then begin
pnl := GridPanel2.ControlCollection[ii].Control as TPanel;
GridPanel2.ControlCollection.RemoveControl(pnl);
freeandnil(pnl);
end;
end;
gridpanel2.Refresh();
end;
如果该面板是集合中的最后一个面板,则效果很好。如果我尝试删除带有 tag = 1 或 tag = 2 的面板,我会收到超出范围的错误。在调试器中单击 "continue" 会在删除的面板所在的位置留下 space,因此删除面板。
我想看到的是,假设面板 2 被移除,随后的面板移动到一个位置以不留空隙。
我该怎么做?
如果重要的话,我正在使用 Delphi 10.1 Berlin。
与往常一样,从列表或集合中删除项目时,您需要在计数发生变化时采取预防措施。 for 循环计数在循环开始时确定。现在,如果您从列表中删除一个项目,当 for 循环持续到结束时,您将命中一个不存在的索引。
您可以通过多种方式避免这种情况,f.ex。找到并删除该项目后,通过跳出循环。
freeandnil(pnl);
break;
另一种方法,是运行 for 循环向后
for ii := GridPanel2.ControlCollection.Count -1 downto 0 do begin
或者您可以使用 Repeat Until
或 While
循环检查条件以在循环的每一圈继续。
要在删除项目后更新网格面板,请调用
中的一个或两个 gridpanel2.UpdateControlsRow();
gridPanel2.UpdateControlsColumn();
不过,要弄对顺序感觉还是挺棘手的