从TGridPanel中移除控件

3

我正在使用 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;

只要该面板是集合中的最后一个面板,它就能正常工作。如果我尝试删除标签为1或2的面板,就会出现超出范围的错误。在调试器中点击“继续”会留下已删除面板的空白,但确实删除了面板。
我想看到的是,比如说删除第二个面板,并将随后的面板向下移动一个位置,以便不留下任何间隔。
我该如何做?
我正在使用Delphi 10.1 Berlin,如果有关系的话。

1
反转你的循环,GridPanel2.ControlCollection.Count -1 downto 0 - Dalija Prasnikar
谢谢你,@DalijaPrasnikar。我错过了一个循环的Break。由于每个标签值都是唯一的,只有一个面板将被删除。这修复了超出范围错误,但没有解决其余面板的混乱问题。再次感谢。 - Michael Vincent
我撤销了您的编辑,因为您删除了问题存在的全部原因。添加“break”后,您所描述的问题就不会出现,因此该问题对于未来的读者没有任何价值。在别人根据贴子中的错误回答之后,编辑代码并删除发帖原因是不恰当的。这样做不仅浪费了那个人的时间,而且完全否定了回答,可能导致该个人由于针对现在不正确的答案投票而失去声望。 - Ken White
@KenWhite 谢谢。 - Michael Vincent
1个回答

2

在从列表或集合中删除项目时,当计数发生变化时,您需要采取预防措施。 for循环计数在循环开始时确定。现在,如果您从列表中删除一个项目,则在for循环继续到达末尾时会遇到不存在的索引。

您可以通过许多方式避免这种情况,例如一旦找到并删除该项,就可以退出循环。

  freeandnil(pnl);
  break;

另一种方法是反向运行for循环

  for ii := GridPanel2.ControlCollection.Count -1 downto 0 do begin

你可以使用重复直到循环来检查每次循环是否满足条件。
在删除项目后更新网格面板,请调用以下任一或两个方法。
  gridpanel2.UpdateControlsRow();
  gridPanel2.UpdateControlsColumn();

然而,让顺序正确感觉相当棘手。

谢谢,是因为缺少了一个break语句导致了越界错误。说实话,我简直不敢相信我会错过它。我会尝试使用UpdateControlsXXX(),看看能否让它们正常工作。再次感谢。 - Michael Vincent
好的,UpdateControlsXXX() 工作了。我使用零作为参数,并按照您提供的顺序使用它们。再次感谢,@TomBrunberg - Michael Vincent

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接