GVKun编程网logo

delphi – 如何在TList中存储动态数组?(delphi tlist用法)

11

本篇文章给大家谈谈delphi–如何在TList中存储动态数组?,以及delphitlist用法的知识点,同时本文还将给你拓展Delphi4的动态数组、DelphiTListView(TListBox

本篇文章给大家谈谈delphi – 如何在TList中存储动态数组?,以及delphi tlist用法的知识点,同时本文还将给你拓展Delphi 4 的动态数组、Delphi TListView(TListBox+图标显示)、Delphi XE8在TList中的错误,需要解决方法、delphi – 在TListView中就地编辑子项等相关知识,希望对各位有所帮助,不要忘了收藏本站喔。

本文目录一览:

delphi – 如何在TList中存储动态数组?(delphi tlist用法)

delphi – 如何在TList中存储动态数组?(delphi tlist用法)

我需要存储未知数量的组.每个组都有未知数量的元素/项目.
这是我的’小组’:
TGroup= array of Integer;     <------ dynamic array (as you can see) :)

我想用TList来保持我的团队.我的想法是,我可能希望稍后访问这些组并向其添加更多项目.

我有这个代码,但我不能让它工作:

TYPE
   TGroup= array of Integer;                              // Each group has x items (x can be from 1 to 10000)


procedure TForm1.FormCreate(Sender: TObject);
VAR CurGroup: TGroup;
    grp,item: Integer;
    Groups: TList;                                        // can contain up to 1 million groups
begin
 Groups:= TList.Create;

 { Init }
 for grp:= 1 to 4  DO                                     // Put a dummy item in TList
  begin
   SetLength(CurGroup,1);                                // Create new group
   Groups.Add(@CurGroup);                                 // Store it
  end;

 CurGroup:= NIL;                                          // Prepare for next use

 for grp:= 1 to 4  DO                                     // We create 4 groups. Each group has 3 items
  begin
    CurGroup:= Groups[Groups.Count-1];                    // We retrieve the current group from list in order to add more items to it

    { We add few items }
    for item:= 0 to 2  DO
     begin
       SetLength(CurGroup,Length(CurGroup)+1);           // reserve space for each new item added
       CurGroup[item]:= Item;
     end;

    Groups[Groups.Count-1]:= @CurGroup;                   // We put the group back into the list
  end;

 { Verify }
 CurGroup:= NIL;
 CurGroup:= Groups[0];
 Assert(Length(CurGroup)> 0);                             // FAIL
 if  (CurGroup[0]= 0)
 AND (CurGroup[1]= 1)
 AND (CurGroup[2]= 2)
 then Application.ProcessMessages;                        

 FreeAndNil(Groups);
end;

注意:代码已完成.您可以将其粘贴到Delphi(7)中进行试用.

解决方法

我已经创建了一个围绕动态数组RTTI的包装器.

这只是初稿,但它的灵感来自你的问题,以及TList方法缺失的事实.

type
  TGroup: array of integer;

var 
  Group: TGroup;
  GroupA: TDynArray;
  i,v: integer;
begin
  GroupA.Init(TypeInfo(TGroup),Group); // associate GroupA with Group
  for i := 0 to 1000 do begin
    v := i+1000; // need argument passed as a const variable
    GroupA.Add(v);
  end;
  v := 1500;
  if GroupA.IndexOf(v)<0 then // search by content
    ShowMessage('Error: 1500 not found!');
  for i := GroupA.Count-1 downto 0 do
    if i and 3=0 then
      GroupA.Delete(i); // delete integer at index i
end;

这个TDynArray包装器也可以用于字符串数组或记录数组…记录只需要打包并且只有引用计数字段(byte,integer,double …)或字符串引用计数字段(没有变量也没有接口内).

IndexOf()方法将按内容进行搜索.那是例如对于记录数组,所有记录字段(包括字符串)必须匹配.

请参阅源代码存储库中的the SynCommons.pas unit中的TDynArray.适用于Delphi 6到XE,并处理Unicode字符串.

TTestLowLevelCommon._TDynArray方法是与此包装器关联的自动单一测试.您将在此处找到记录数组和更高级功能的示例.

我目前正在实现SavetoStream和LoadToStream方法……

也许是在所有Delphi版本中使用类通用特性的新方法.

编辑:

我在TDynArray记录/对象中添加了一些新方法:

>现在,您可以将动态数组内容保存到字符串或从字符串加载(使用LoadFromStream / SavetoStream或LoadFrom / Saveto方法) – 它将使用专有但非常快速的二进制流布局;
>并且您可以通过两种方式对动态数组内容进行排序:就地(即交换数组元素内容)或通过外部整数索引查找数组(使用CreateOrderedindex方法 – 在这种情况下,您可以有几个订单到同一数据);
>您可以指定任何自定义比较函数,并且有一个新的Find方法可以使用快速二进制搜索(如果可用).

以下是这些新方法的工作原理:

var
  Test: RawByteString;
...
  Test := GroupA.Saveto;
  GroupA.Clear;
  GroupA.LoadFrom(Test);
  GroupA.Compare := SortDynArrayInteger;
  GroupA.sort;
  for i := 1 to GroupA.Count-1 do
    if Group[i]<Group[i-1] then
      ShowMessage('Error: unsorted!');
  v := 1500;
  if GroupA.Find(v)<0 then // fast binary search
    ShowMessage('Error: 1500 not found!');

更接近通用范例,更快,对于Delphi 6到XE …

Delphi 4 的动态数组

Delphi 4 的动态数组

总结

以上是小编为你收集整理的Delphi 4 的动态数组全部内容。

如果觉得小编网站内容还不错,欢迎将小编网站推荐给好友。

Delphi TListView(TListBox+图标显示)

Delphi TListView(TListBox+图标显示)

分享图片

unit Unit1;

interface

uses
  Winapi.Windows,Winapi.Messages,System.SysUtils,System.Variants,System.Classes,Vcl.Graphics,Vcl.Controls,Vcl.Forms,Vcl.Dialogs,System.ImageList,Vcl.ImgList,Vcl.StdCtrls,Vcl.ComCtrls;

type
  TForm1 = class(TForm)
    lv1: TListView;
    添加: TButton;
    il1: timageList;
    btn删除选中: TButton;
    清空: TButton;
    btnDelete_select: TButton;
    procedure 添加Click(Sender: TObject);
    procedure btn删除选中Click(Sender: TObject);
    procedure btnDelete_selectClick(Sender: TObject);
    procedure 清空Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.添加Click(Sender: TObject);
begin
  if lv1.Columns.Count = 0 then
    lv1.Columns.Add.Caption := 111;

  lv1.Column[0].width := 200;
  with lv1.Items.Add do
  begin
    StateIndex := 2;
    Caption := Item + IntToStr(lv1.Items.Count);
  end;

end;

procedure TForm1.清空Click(Sender: TObject);
begin
  lv1.Clear;
end;

procedure TForm1.btnDelete_selectClick(Sender: TObject);
begin
  lv1.Items[1].Delete;
end;

procedure TForm1.btn删除选中Click(Sender: TObject);
begin
  lv1.Selected.Delete;
end;

end.

Delphi XE8在TList中的错误,需要解决方法

Delphi XE8在TList中的错误,需要解决方法

升级到XE8后,我们的一些项目开始中断数据。看起来像一个在TList实现中的错误。
program XE8Bug1;
{$APPTYPE CONSOLE}

uses
  System.SysUtils,Generics.Collections;

type
  TRecord = record
    A: Integer;
    B: Int64;
  end;

var
  FRecord: TRecord;
  FList: TList<TRecord>;

begin
  FList := TList<TRecord>.Create;
  FRecord.A := 1;
  FList.Insert(0,FRecord);
  FRecord.A := 3;
  FList.Insert(1,FRecord);
  FRecord.A := 2;
  FList.Insert(1,FRecord);
  Writeln(IntToStr(FList[0].A) + IntToStr(FList[1].A) + IntToStr(FList[2].A));

end.

此代码在XE7和之前(应该是)打印“123”,但在XE8中打印“120”。
也许有人知道一个quickfix这个?

更新:非官方修订是here

解决方法

我发现现在TList< T> .Insert方法调用TListHelper.InternalInsertX取决于数据大小,在我的情况下:
procedure TListHelper.InternalInsertN(AIndex: Integer; const Value);
var
  ElemSize: Integer;
begin
  CheckInsertRange(AIndex);

  InternalGrowCheck(FCount + 1);
  ElemSize := ElSize;
  if AIndex <> FCount then
    Move(PByte(FItems^)[AIndex * ElemSize],PByte(FItems^)[(AIndex * ElemSize) + 1],(FCount - AIndex) * ElemSize);
  Move(Value,PByte(FItems^)[AIndex * ElemSize],ElemSize);
  Inc(FCount);
  FNotify(Value,cnAdded);
end;

我看到第一个Move调用中的问题。目标应为:

PByte(FItems^)[(AIndex + 1) * ElemSize]

PByte(FItems^)[(AIndex * ElemSize) + 1]

Aaargh!

最后,我在我的项目中使用了来自Delphi XE7的System.Generics.Defaults.pas和System.Generics.Collections.pas单元,现在所有的工作都如预期的那样。

更新:如我所见,RTL不受影响,因为它不使用TList&T。为SizeOf&T插入T。 8(或者我可能错过了什么?)

delphi – 在TListView中就地编辑子项

delphi – 在TListView中就地编辑子项

我有一个包含3列的ListView,想要编辑第三列,也就是Subitem [1].如果我将ListView.ReadOnly设置为True,它允许我编辑所选项目的标题.是否有一种简单的方法为子项目做同样的事情?我想远离在编辑上面添加无边框控件.

解决方法

您可以使用TEdit,自定义消息编辑listview的子项(在报告模式下)并处理ListView的OnClick事件.

试试这个样本

Const
  USER_EDITLISTVIEW = WM_USER + 666;

type
  TForm1 = class(TForm)
    ListView1: TListView;
    procedure FormCreate(Sender: TObject);
    procedure ListView1Click(Sender: TObject);
  private
    ListViewEditor: TEdit;
    LItem: TListitem;
    procedure UserEditListView( Var Message: TMessage ); message USER_EDITLISTVIEW;
    procedure ListViewEditorExit(Sender: TObject);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses
  CommCtrl;
const
  EDIT_COLUMN = 2; //Index of the column to Edit

procedure TForm1.FormCreate(Sender: TObject);
Var
  I : Integer;
  Item : TListItem;
begin
  for I := 0 to 9 do
  begin
   Item:=ListView1.Items.Add;
   Item.Caption:=Format('%d.%d',[i,1]);
   Item.SubItems.Add(Format('%d.%d',2]));
   Item.SubItems.Add(Format('%d.%d',3]));
  end;

  //create the TEdit and assign the OnExit event
  ListViewEditor:=TEdit.Create(Self);
  ListViewEditor.Parent:=ListView1;
  ListViewEditor.OnExit:=ListViewEditorExit;
  ListViewEditor.Visible:=False;
end;

procedure TForm1.ListView1Click(Sender: TObject);
var
  LPoint: TPoint;
  LVHitTestInfo: TLVHitTestInfo;
begin
  LPoint:= listview1.ScreenToClient(Mouse.CursorPos);
  ZeroMemory( @LVHitTestInfo,SizeOf(LVHitTestInfo));
  LVHitTestInfo.pt := LPoint;
  //Check if the click was made in the column to edit
  If (ListView1.perform( LVM_SUBITEMHITTEST,LParaM(@LVHitTestInfo))<>-1) and ( LVHitTestInfo.iSubItem = EDIT_COLUMN ) Then
    PostMessage( self.Handle,USER_EDITLISTVIEW,LVHitTestInfo.iItem,0 )
  else
    ListViewEditor.Visible:=False; //hide the TEdit 
end;

procedure TForm1.ListViewEditorExit(Sender: TObject);
begin
  If Assigned(LItem) Then
  Begin
    //assign the vslue of the TEdit to the Subitem
    LItem.SubItems[ EDIT_COLUMN-1 ] := ListViewEditor.Text;
    LItem := nil;
  End;
end;

procedure TForm1.UserEditListView(var Message: TMessage);
var
  LRect: TRect;
begin
  LRect.Top := EDIT_COLUMN;
  LRect.Left:= LVIR_BOUNDS;
  listview1.Perform( LVM_GETSUBITEMRECT,Message.wparam,LParaM(@LRect) );
  MapWindowPoints( listview1.Handle,ListViewEditor.Parent.Handle,LRect,2 );
  //get the current Item to edit
  LItem := listview1.Items[ Message.wparam ];
  //set the text of the Edit 
  ListViewEditor.Text := LItem.Subitems[ EDIT_COLUMN-1];
  //set the bounds of the TEdit
  ListViewEditor.BoundsRect := LRect; 
  //Show the TEdit
  ListViewEditor.Visible:=True;
end;

关于delphi – 如何在TList中存储动态数组?delphi tlist用法的问题我们已经讲解完毕,感谢您的阅读,如果还想了解更多关于Delphi 4 的动态数组、Delphi TListView(TListBox+图标显示)、Delphi XE8在TList中的错误,需要解决方法、delphi – 在TListView中就地编辑子项等相关内容,可以在本站寻找。

本文标签: