Removing controls from a TGridPanel

北慕城南 提交于 2019-12-23 20:22:47

问题


I'm using TGridPanel to manage a number of panels. I create the panels and add them to the GridPanel using code like the following:

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;

You will notice that each panel has a different tag value.

I'd like to remove a panel from the GridPanel based on the value in the panel's tag property. I have tried the following code:

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;

This works well providing the panel is the last panel in the collection. If I try to remove the panel with tag = 1 or tag = 2 I get an out of range error. Clicking "continue" in the debugger leaves a space where the removed panel was, so does remove the panel.

What I'd like to see is, say panel 2 removed and subsequent panels shuffled down one place to leave no gaps.

How do I do this?

I'm using Delphi 10.1 Berlin if that matters.


回答1:


As always when deleting an item from a list or collection you need to take precaution when the count changes. A for loop count is determined at the beginning of the loop. Now, if you delete an item from the list you will hit a non-existing index when the for loop continues to the end.

You can avoid this in many ways, f.ex. by breaking out of the loop, once you have found and deleted the item.

  freeandnil(pnl);
  break;

Another way, is to run the for loop backwards

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

Or you can use Repeat Until or Whileloops which checks the condition to continue on every turn of the loop.

To update the grid panel after deleting items call either or both of

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

However, it feels quite tricky to get the order right



来源:https://stackoverflow.com/questions/37589677/removing-controls-from-a-tgridpanel

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!