从 TGridPanel 中删除控件

Posted

技术标签:

【中文标题】从 TGridPanel 中删除控件【英文标题】:Removing controls from a TGridPanel 【发布时间】:2016-06-02 10:47:43 【问题描述】:

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

您会注意到每个面板都有不同的标记值。

我想根据面板的 tag 属性中的值从 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 删除面板,则会出现超出范围的错误。在调试器中单击“继续”会在已删除面板所在的位置留下一个空间,删除面板也是如此。

我希望看到的是,假设面板 2 被移除,随后的面板移动到一个位置以不留空隙。

我该怎么做?

如果重要的话,我正在使用 Delphi 10.1 Berlin。

【问题讨论】:

反转你的循环,GridPanel2.ControlCollection.Count -1 downto 0 谢谢你,@DalijaPrasnikar。我错过了一次Break out of the loop。由于每个标签值都是唯一的,因此只会删除一个面板。这修复了超出范围的错误,但没有修复剩余面板的改组。再次感谢, 我回滚了您的编辑,因为您已经删除了问题存在的全部原因。添加break后,您描述的问题不会发生,因此该问题对这里的未来读者没有任何价值。编辑代码并删除发布的全部原因是不合适的,尤其是在有人根据帖子中的错误回答之后。你不仅浪费了那个人的时间,而且你完全否定了这个答案,这可能导致那个人因为对那个现在不正确的答案投票而失去声誉。 @KenWhite 谢谢。 【参考方案1】:

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

您可以通过多种方式避免这种情况,f.ex。一旦您找到并删除了该项目,就可以跳出循环。

  freeandnil(pnl);
  break;

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

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

或者您可以使用Repeat UntilWhileloops 来检查在循环的每一轮都继续的条件。

删除项目后更新网格面板调用其中一个或两个

  gridpanel2.UpdateControlsRow();
  gridPanel2.UpdateControlsColumn();

但是,正确的顺序感觉相当棘手

【讨论】:

谢谢,正是缺少中断导致了越界错误。老实说,我不敢相信我错过了它。我会试试 UpdateControlsXXX() 看看我是否能让它们工作。再次感谢, 好吧,UpdateControlsXXX() 工作。我使用零作为参数并使用它们的顺序。再次感谢@TomBrunberg

以上是关于从 TGridPanel 中删除控件的主要内容,如果未能解决你的问题,请参考以下文章

某处有更好的 TGridPanel 吗?

JavaFX:如何从 GridPane 中动态创建的文本字段的值计算平均值?

javafx窗体面板位置

JavaFX中GridPane的行居中对齐

Javafx 中 GridPane 中的 HBox

JavaFX:将图像插入 GridPane