Trouble synchronizing generic TList and TListBox

2019-06-02 07:20发布

问题:

I have trouble keeping a TListbox in sync with a TList. Each time an item is added to a generic TList, OnNotify is called and the callback calls just one procedure: create_gradients. Its code is below:

  procedure TColor_Dialog.create_gradients;
  var Editor: TGradient_Editor;
      eGradient: Int32;
      y: single;
      s: string;
  begin
     List_Names.Clear;
     List_Gradients.Clear;

     for eGradient := 0 to FColor_Editor.nGradients - 1 do
     begin
        List_Names.Items.Add (FColor_Editor [eGradient].Check_Rainbow.Text);
     end; // for

     List_Gradients.BeginUpdate;
     try
        for eGradient := 0 to FColor_Editor.nGradients - 1 do
        begin
           Editor := FColor_Editor [eGradient];
           y := (eGradient + 1) * Editor.Height;
           Editor.Position.Y := y;
           s := Editor.Check_Rainbow.Text;
           List_Gradients.AddObject (Editor);
        end; // for
     finally
        List_Gradients.EndUpdate;
     end; // try..finally
  end; // create_gradients //

As you see it simply enumerates all items in the list. Each item in the list is a TGradient_Editor which in turn has TFrame as a parent. On the parent are some FMX controls as combolorboxes, an image and a checkbox (Check_Rainbow). Check_Rainbow.Text is used for identification purposes. When the gradient editor is created, it creates a unique name from frame_%s where %s is a sequence number that is incremented each time a gradient editor is created. Owner and Parent are both List_Gradients.

From the image above you can see what happens. the listbox on the right is added for checking and just shows the text's, which is the correct sequence by the way. When I use the debugger to follow the addition of the gradient editors to List_Gradient they are processed in the same order. But the order of the gradient editors is wrong. I have to mention that the aligment of the gradient editors is alTop. I added even some code to ensure that the editor is Positioned at the very bottom of the List_Gradients.

I appear not to understand something. I cannot imagine that sequential adding to a TListBox cannot result in the correct order. What am I doing wrong?

回答1:

Try this instead:

procedure TColor_Dialog.create_gradients;
var
  Editor: TGradient_Editor;
  eGradient: Int32;
  y: single;
begin
  List_Names.Clear;
  List_Gradients.Clear;

  for eGradient := 0 to FColor_Editor.nGradients - 1 do
  begin
    List_Names.Items.Add (FColor_Editor[eGradient].Check_Rainbow.Text);
  end;

  List_Gradients.BeginUpdate;
  try
    y := 0.0; // or whatever value you want to start at...
    for eGradient := 0 to FColor_Editor.nGradients - 1 do
    begin
      Editor := FColor_Editor[eGradient];
      Editor.Position.Y := y;
      List_Gradients.AddObject(Editor);
      y := y + Editor.Height;
    end;
  finally
    List_Gradients.EndUpdate;
  end;
end;


回答2:

As requested I moved the answer to this section. The correct code is:

  procedure TColor_Dialog.create_gradients;
  var Editor: TGradient_Editor;
      eGradient: Int32;
      y: single;
  begin
     List_Gradients.BeginUpdate;
     try
        List_Gradients.Clear;
        y := 0;
        for eGradient := 0 to FColor_Editor.nGradients - 1 do
        begin
           Editor := FColor_Editor [eGradient];
           Editor.Position.X := 0;
           Editor.Position.Y := y;
           Editor.Width := List_Gradients.Width;
           List_Gradients.AddObject (Editor);
           y := y + Editor.Height;
        end; // for
     finally
        List_Gradients.EndUpdate;
     end; // try..finally
  end; // create_gradients //

and not using any alignment anymore. Adding Objects to a TListBox is a real nice feature of FMX. However, be prepared that things sometimes work differently than you expect. For one thing: objects are not positioned in the same way as strings.