TStringGrid性能不佳

awm*_*oss 6 delphi

我有一个包含10列的TStringGrid.添加500行需要大约2秒钟.这是正常的表现吗?

对我来说似乎有点慢.

我从数据库查询中获取数据.如果我遍历查询但不将结果写入StringGrid,则该过程大约需要100毫秒,因此数据库不会减慢速度.

添加行后,StringGrid性能很好.

这是我正在使用的代码

Grid.RowCount := Query.RecordCount;
J := 0;

while not Query.EOF do
begin
    Grid.Cells[0,J]:=Query.FieldByName('Value1').AsString;
    Grid.Cells[1,J]:=Query.FieldByName('Value2').AsString;
    Grid.Cells[2,J]:=Query.FieldByName('Value3').AsString;
    // etc for other columns.
    Inc(J);
    Query.Next();
end;
Run Code Online (Sandbox Code Playgroud)

实际代码实际上有点复杂(表列与查询列不完全对应),但这是基本的想法

shu*_*nty 7

我发现在执行大量记录时非常重要的另一件事是为每个字段使用适当的TField变量.FieldByName每次迭代Fields集合,因此不是最高性能的选项.在循环之前定义每个字段,如:

var
  f1, f2: TStringField;
  f3: TIntegerField;

begin
  // MyStringGrid.BeginUpdate; // Can't do this
  // Could try something like this instead:
  // MyStringGrid.Perform(WM_SETREDRAW, 0, 0);
  try
    while ... do
    begin
      rowvalues[0] := f1.AsString;
      rowvalues[1] := f2.AsString;
      rowvalues[2] := Format('%4.2d', f3.AsInteger);
      // etc 
    end;
  finally
    // MyStringGrid.EndUpdate; // Can't - see above
    // MyStringGrid.Perform(WM_SETREDRAW, 1, 0);
    // MyStringGrid.Invalidate;
  end;
end;
Run Code Online (Sandbox Code Playgroud)

这与BeginUpdate/Endupdate一起并在适当时调用Query.DisableControls.


awm*_*oss 6

解决方案是使用"行"属性一次性添加所有值.

我的代码现在看起来像这样:

Grid.RowCount := Query.RecordCount;
rowValues:=TStringList.Create;
J := 0;

while not Query.EOF do
begin
    rowValues[0]:=Query.FieldByName('Value1').AsString;
    rowValues[1]:=Query.FieldByName('Value2').AsString;
    rowValues[2]:=Query.FieldByName('Value3').AsString;
    // etc for other columns.
    Grid.Rows[J]:=rowValues;
    Inc(J);
    Query.Next();
end;

rowValues.Free; // for the OCD among us
Run Code Online (Sandbox Code Playgroud)

这使得时间从2秒减少到大约50毫秒.

  • 您还应该在此操作期间锁定stringgrid.Grid.Cols [0] .BeginUpdate,Try(设置RowCount和填充行)最后Grid.Cols [0] .EndUpdate.这有点奇怪,但这个技巧锁定了整个网格,而不仅仅是列. (4认同)
  • 说实话,我不明白速度差异.这意味着`Grid.Cells`访问非常慢,我怀疑......有人可以解释这个吗? (2认同)