Я хочу назначить запись для TStringList.Objects

Я хочу создать элемент управления Playlist. У меня много информации для отображения в TStringList. Я хочу назначить запись для TStringGrid.Objects вместо объекта, потому что для создания / уничтожения такого количества объектов может потребоваться некоторое время. Это также занимает много оперативной памяти.

Запись будет намного быстрее и стройнее. Как я могу это сделать?

TYPE
 AMyRec= packed record
        FullName     : string[255];    
        RelativePath : boolean;        
        IsInvalid    : boolean;        
        InCache      : boolean;        
        etc
       end;
14.12.2008 23:06:29
Как вы создаете свои записи? Использование New (PMyRec) займет аналогичное время (или любой другой метод, который создает их в куче)
Gerry Coll 14.12.2008 23:26:36
5 ОТВЕТОВ

Вы можете использовать запись указателя.

List.AddObject(MyRecord.FullName, @MyRecord);
1
5.03.2009 00:43:12
Нет, ты не можешь этого сделать. Запись превышает четыре байта. Квадратный колышек, круглое отверстие.
Rob Kennedy 15.12.2008 00:45:07
Да, ты можешь. Каждый Tlist имеет 4-байтовый объект, который вы можете использовать для любых целей. Вы можете выделить свою запись и установить этот объект как указатель на запись, чтобы вы могли легко найти ее. Так что это правильный ответ.
lkessler 15.12.2008 03:15:47
Разве вам не нужно убедиться, что вы поместили запись в кучу, а не в стек? Если он находится в стеке, он будет устаревшим, когда выйдет из области видимости.
Jim McKeeth 15.12.2008 04:08:48
Это будет @MyRecord и не будет работать вне метода, поскольку запись основана на привязке.
Lars Truijens 15.12.2008 08:23:36
Это не будет работать, потому что запись не является ни объектом, ни указателем. Вы должны убедиться, что запись хранится в куче и назначить указатель на нее в списке.
Thomas Mueller 15.12.2008 10:04:51

Выделение памяти для записей занимает также время.

создайте свою запись и поместите указатель на объекты в списке строк.

0
14.12.2008 23:23:07

Вы можете использовать TList для указателя вашей записи.

Например:

Type    
PMyrec = ^AMyRec;

Применение

var
   MyRec : PMyRec;
new(MyRec);
MyRec^.Fullname := 'test';
MyRec^.RelativePath := false;

так далее

{MyList - это список, который вы создали в другом месте}

MyList.Add(MyRec);

Вам придется обрабатывать удаление предметов из списка, например

Dispose(PMyRec(MyList[Index]));

Чтобы использовать элемент из списка:

var
  MyRec : PMyRec;

PMyRec := MyList.Items[i];
txtBox.Text = PMyRec^.Fullname;

так далее

6
17.12.2008 21:43:36

Решено
Я попробовал что-то подобное сейчас (на примере KiwiBastard):

Type
 AMyRec= packed record
        FullName     : string[255];
        RelativePath : boolean;
        IsInvalid    : boolean;
       end;
 PMyrec = ^AMyRec;

procedure TPlaylst.Button1Click(Sender: TObject);
VAR MyRec1: PMyRec;
    PlaylistCtrl: TStringGrid;
begin
 {SET}
 new(MyRec1);
 MyRec1^.Fullname := 'test';
 MyRec1^.RelativePath := false;
 PlaylistCtrl.Objects[1,1]:= Pointer(MyRec1); 


 {GET}
 ...
end;

1
27.01.2013 13:32:57
Опять же, просто выполните приведение типа: PlaylistCtrl.Objects [1,1]: = Pointer (MyRec1); и наоборот, чтобы получить данные обратно: MyRec: = TMyRec (PlaylistCtrl.Objects [1,1]);
Mike Sutton 15.12.2008 00:36:51
Объект на четыре байта больше соответствующей записи. И второе приведение типов Майка должно быть к PMyRec, а не к TMyRec.
Rob Kennedy 15.12.2008 00:49:15
Таким образом, использование записей вместо объектов будет «съесть» примерно столько же ОЗУ?
Migrate2Lazarus see my profile 15.12.2008 01:19:49
Вы действительно должны отредактировать оригинал или создать новый вопрос. Правильный ответ на оригинальный вопрос уже дан. Стек переполнения работает лучше всего, когда его один вопрос, все возможные ответы.
skamradt 15.12.2008 03:45:23

Вы уверены, что готовы выделить все эти объекты? Судя по структуре записи, создается впечатление, что вы хотите получить объект в строке, а не в ячейке. Для этого у вас есть как минимум 2 варианта:

  1. (Мой любимый из-за свободы, которую он дает) Вместо этого вы используете TDrawGrid и вручную рисуете содержимое своей ячейки. Это действительно не так сложно!
  2. Вы делаете объект, который инкапсулирует эту запись. Это также легко, как, например:

type
  TMyRec= packed record
    FullName     : string[255];
    RelativePath : boolean;
    IsInvalid    : boolean;
  end;
  TMyData = object (TObject)
  private
    FData: TMRec;
  public
    constructor Create(AData: TMyRec);
    property FullName: String read FData.FullName write FData.FullName;
    property RelativePath: Boolean read FData.RelativePath write FData.RelativePath;
    property IsInvalid: Boolean read FData.IsInvalid write FData.IsInvalid;
  end;

...

constructor TMyData.Create(AData: TMyRec);
begin
  FData := AData;
end;

Теперь, когда вы хотите подключить ваши данные к сетке, вы просто упаковываете их в этот объект и затем можете использовать коллекцию объектов.

Теперь вместо того, чтобы проходить через все это, просто создайте обработчик событий для TDrawGrid.DrawCell, например

procedure TMainForm.GrdPathsDrawCell(Sender: Object; ...);

используйте GrdPaths.Canvas.Handle с DrawText или, если нужен Unicode, используйте DrawTextW (оба взяты из Windows API, так что есть множество примеров его использования), и вы сэкономите вам и вашему клиенту много разочарований, памяти и, прежде всего, время

1
30.12.2008 20:47:26