0

我在 Delphi XE4(在 Windows 7 环境中)中动态调整 TJVListview 的列宽时遇到问题。应用程序需要更长的时间来调整列大小,如果列表视图上有大量数据,有时会引发访问冲突。我们正在使用下面的代码来调整列的大小。

for i := 0 to LV.Columns.Count -1 do
begin
  if LV.Columns.Items[i].Tag = 0 then
  begin
    LV.Columns.Items[i].Width := ColumnTextWidth;
    LV.Columns.Items[i].Width := ColumnHeaderWidth;
  end;
end;

以前相同的代码在 Delphi 2009 上也能正常工作。我只在使用 customdrawitem 事件时才注意到这个问题(我们在列表视图中放置图像的位置)。对于只有文本显示的普通列表视图,上面的代码工作正常。

我尝试通过将 Column AutoSize 属性设置为 true 来使用它,但它没有用。

关于如何克服这个问题的任何建议。实际上,我们在应用程序的许多地方都使用了 TJVlistview 组件。

问候,西兰。

代码 :

1) 在我的表单中,我有一个 JVListview、Button 和 imagelist。用于加载到列表视图的按钮。2)在Advancecustomdrawitem中,我尝试放置一个BMP控件并执行替代行颜色更改...

procedure TForm1.Button1Click(Sender: TObject);
var
  i, ii: Integer;
  ListItem: TListItem;
  strVal : String;
begin
  strVal := 'Test String';
  try
    ListView.Items.BeginUpdate;
    LockWindowUpdate(listview.handle);
    try
      ListView.Clear;
      for i := 1 to 15 do
      begin
        ListItem := ListView.Items.Add;
        ListItem.SubItems.Add(strVal +'_' +IntToStr(i));
        ListItem.SubItems.Add(strVal +'_' +IntToStr(i));
        ListItem.SubItems.Add(strVal +'_' +IntToStr(i));
        ListItem.SubItems.Add(strVal +'_' +IntToStr(i));
        ListItem.SubItems.Add(strVal +'_' +IntToStr(i));
     end;
    finally
      // for resizing the columns based on the text size
      FitToTextWidth(ListView);
      ListView.Items.EndUpdate;
      LockWindowUpdate(0);
    end;
  except
    on E: Exception do
      MessageDlg(PWideChar(E.Message), TMsgDlgType.mtError, [TMsgDlgBtn.mbOK], 0);
  end;
end;


procedure TForm1.FitToTextWidth(LV: TListView);
var
i : integer;
begin
  // Set the Column width based on based on textwidth and headerwidth
  for i := 0 to LV.Columns.Count -1 do
  begin
    if LV.Columns.Items[i].Tag = 0 then
    begin
      LV.Columns.Items[i].Width := ColumnTextWidth;
      LV.Columns.Items[i].Width := ColumnHeaderWidth;
    end;
  end;
end;

procedure TForm1.LISTVIEWAdvancedCustomDrawItem(Sender: TCustomListView;
  Item: TListItem; State: TCustomDrawState; Stage: TCustomDrawStage;
  var DefaultDraw: Boolean);
       Var
R   : TRect;
C : TCanvas;
B : TBitMap;
begin
  // Set C
  C := (Sender as TListView).Canvas;
  // Set R
  R := Item.DisplayRect(drLabel);
  B := TBitMap.Create;
  B.Transparent := True;
  B.TransparentColor := clWhite;
  // based on item index set the image and change the row color
  if odd(item.Index) = true then
  begin
     ImageList.GetBitmap(0,B);
     TJvListItem( Item ).Brush.Color := clWhite;
     TJvListItem( Item ).Font.Color  := clBlack;
  end
  else
  begin
    ImageList.GetBitmap(1,B);
    TJvListItem( Item ).Brush.Color := clMoneyGreen;
    TJvListItem( Item ).Font.Color  := clBlack;
  end;
  C.Draw(R.Left + 5 ,R.Top, B);
  B.Free;
end;

上面的代码在 Delphi 2009 上运行良好......但目前正在尝试在 Win 7 环境中迁移到 XE4.. 我的问题是,加载列表视图需要大量时间(通过调用 FitToTextWidth 方法动态调整列大小时)。 .但没有这种方法,它工作正常,但没有调整列大小......

4

1 回答 1

1

当您将列的宽度设置为任何一个自动常量时,控件必须评估项目/子项目的长度才能计算必要的宽度。这需要时间。

此外,当您设置列的宽度时,VCL ListView 会更新所有列。

您有六列,设置其中任何一列的宽度涉及 6 列更新,加上FitToTextWidth程序中的虚假调用,您的代码导致读取列的所有项目/子项目 42 次(由于 VCL 中的代码路径:第 1 列 1 次,第 2 列 2 次 -> 21 次用于设置 6 列的宽度)。将您的宽度设置包含在 Begin/EndUpdate 调用中并删除额外的调用,您将在 6 轮内完成它。

procedure TForm1.FitToTextWidth(LV: TListView);
var
i : integer;
begin
  // Set the Column width based on based on textwidth and headerwidth
  LV.Columns.BeginUpdate;
  try
    for i := 0 to LV.Columns.Count -1 do
    begin
      if LV.Columns.Items[i].Tag = 0 then
      begin
//        LV.Columns.Items[i].Width := ColumnTextWidth;
        LV.Columns.Items[i].Width := ColumnHeaderWidth;
      end;
    end;
  finally
    LV.Columns.EndUpdate;
  end;
end;


由于您的测试用例中没有任何 AV,因此我无法对此发表评论。

于 2013-09-20T12:58:12.113 回答