在Windows10中的Delphi10.4.2win-32VCL应用程序中,我使用一个简单的TListBox将记录存储在ListBox项中。当用户单击某个项时,将检索关联记录的数据:
type
PResizeSettingsRec = ^TResizeSettingsRec;
TResizeSettingsRec = record
TopValue: Integer;
LeftValue: Integer;
RightValue: Integer;
BottomValue: Integer;
Color: TColor;
Opacity: Integer;
end;
procedure TformMain.btnAddCurrentSettingsClick(Sender: TObject);
var
P: PResizeSettingsRec;
begin
New(P);
P.TopValue := 5;
P.LeftValue := 5;
P.RightValue := 5;
P.BottomValue := 5;
P.Color := clRed;
P.Opacity := 255;
listboxMultiResize.AddItem('Step 1', TObject(P));
New(P);
P.TopValue := 9;
P.LeftValue := 9;
P.RightValue := 9;
P.BottomValue := 9;
P.Color := clBlue;
P.Opacity := 127;
listboxMultiResize.AddItem('Step 2', TObject(P));
end;
procedure TformMain.FormDestroy(Sender: TObject);
begin
for var i := 0 to listboxMultiResize.Items.Count - 1 do
Dispose(PResizeSettingsRec(listboxMultiResize.Items.Objects[i]));
end;
procedure TformMain.listboxMultiResizeClick(Sender: TObject);
var
P: PResizeSettingsRec;
begin
if listboxMultiResize.ItemIndex < 0 then EXIT;
P := PResizeSettingsRec(listboxMultiResize.Items.Objects[listboxMultiResize.ItemIndex]);
CodeSite.Send('TformMain.listboxMultiResizeClick: P.TopValue', P.TopValue);
CodeSite.Send('TformMain.listboxMultiResizeClick: P.LeftValue', P.LeftValue);
CodeSite.Send('TformMain.listboxMultiResizeClick: P.RightValue', P.RightValue);
CodeSite.Send('TformMain.listboxMultiResizeClick: P.BottomValue', P.BottomValue);
CodeSite.Send('TformMain.listboxMultiResizeClick: ColorToString(P.Color)', ColorToString(P.Color));
CodeSite.Send('TformMain.listboxMultiResizeClick: P.Opacity', P.Opacity);
end;这种方法是故意简单的,使它稳定和万无一失。或者,是否有更好、更现代、更容易实现这一目标的方法?
是否有一种简单的方法可以将ListBox项及其数据存储到文件中,然后从文件中重新加载它们?(目前,我使用INI文件)。
编辑:遵循Andreas的建议,我现在使用以下代码:
type
TResizeSettings = class
TopValue: Integer;
LeftValue: Integer;
RightValue: Integer;
BottomValue: Integer;
Color: TColor;
Opacity: Integer;
end;
procedure TformMain.btnAddCurrentSettingsClick(Sender: TObject);
var
ThisResizeSettings: TResizeSettings;
begin
ThisResizeSettings := TResizeSettings.Create;
try
ThisResizeSettings.TopValue := 5;
ThisResizeSettings.LeftValue := 5;
ThisResizeSettings.RightValue := 5;
ThisResizeSettings.BottomValue := 5;
ThisResizeSettings.Color := clRed;
ThisResizeSettings.Opacity := 255;
listboxMultiResize.AddItem('Step 1', ThisResizeSettings);
finally
ThisResizeSettings.Free;
end;
ThisResizeSettings := TResizeSettings.Create;
try
ThisResizeSettings.TopValue := 9;
ThisResizeSettings.LeftValue := 9;
ThisResizeSettings.RightValue := 9;
ThisResizeSettings.BottomValue := 9;
ThisResizeSettings.Color := clBlue;
ThisResizeSettings.Opacity := 127;
listboxMultiResize.AddItem('Step 2', ThisResizeSettings);
finally
ThisResizeSettings.Free;
end;
end;
procedure TformMain.FormDestroy(Sender: TObject);
begin
for var i := 0 to listboxMultiResize.Items.Count - 1 do
begin
TResizeSettings(listboxMultiResize.Items.Objects[i]).Free;
end;
end;
procedure TformMain.listboxMultiResizeClick(Sender: TObject);
var
ThisResizeSettings: TResizeSettings;
begin
if listboxMultiResize.ItemIndex < 0 then EXIT;
ThisResizeSettings := TResizeSettings(listboxMultiResize.Items.Objects[listboxMultiResize.ItemIndex]);
CodeSite.Send('TformMain.listboxMultiResizeClick: TopValue', ThisResizeSettings.TopValue);
CodeSite.Send('TformMain.listboxMultiResizeClick: LeftValue', ThisResizeSettings.LeftValue);
CodeSite.Send('TformMain.listboxMultiResizeClick: RightValue', ThisResizeSettings.RightValue);
CodeSite.Send('TformMain.listboxMultiResizeClick: BottomValue', ThisResizeSettings.BottomValue);
CodeSite.Send('TformMain.listboxMultiResizeClick: ColorToString(P.Color)', ColorToString(ThisResizeSettings.Color));
CodeSite.Send('TformMain.listboxMultiResizeClick: Opacity', ThisResizeSettings.Opacity);
end;但是,当单击Listbox项目时,我会得到随机结果!
EDIT2:安德烈亚斯回答之后的现在不再释放创建的对象:
procedure TformMain.btnAddCurrentSettingsClick(Sender: TObject);
// https://stackoverflow.com/questions/68702539/better-approach-for-storing-retrieving-saving-and-loading-data-in-a-tlistbox
var
ThisResizeSettings: TResizeSettings;
begin
ThisResizeSettings := TResizeSettings.Create;
ThisResizeSettings.TopValue := 5;
ThisResizeSettings.LeftValue := 5;
ThisResizeSettings.RightValue := 5;
ThisResizeSettings.BottomValue := 5;
ThisResizeSettings.Color := clRed;
ThisResizeSettings.Opacity := 255;
listboxMultiResize.AddItem('Step 1', ThisResizeSettings);
ThisResizeSettings := TResizeSettings.Create;
ThisResizeSettings.TopValue := 9;
ThisResizeSettings.LeftValue := 9;
ThisResizeSettings.RightValue := 9;
ThisResizeSettings.BottomValue := 9;
ThisResizeSettings.Color := clBlue;
ThisResizeSettings.Opacity := 127;
listboxMultiResize.AddItem('Step 2', ThisResizeSettings);
end;我还更改了ListBox对象在FormDestroy中的释放。
procedure TformMain.FormDestroy(Sender: TObject);
begin
// https://stackoverflow.com/questions/68702539/better-approach-for-storing-retrieving-saving-and-loading-data-in-a-tlistbox
for var i := listboxMultiResize.Items.Count - 1 downto 0 do
begin
listboxMultiResize.Items.Objects[i].Free;
listboxMultiResize.Items.Objects[i] := nil;
end;现在看来起作用了。谢谢安德烈亚斯!
发布于 2021-08-08 18:55:57
不要使用记录,而是使用对象。那么丑陋的TObject转换就不需要了,因为您实际上提供了一个对象!这是(主要)应该使用的方式。
记住:类不需要有getter和setter,默认情况下,TObject-based类具有成员可见性public。如果不需要,则不需要带有getter和setter的私有字段和公共属性。此外,记录是值类型,而对象是引用类型(您需要创建和释放它们),但是在您的示例中,引用类型更方便。此外,你已经在做分配和释放,尽管以一种古老的方式!
下面是一个简单的例子:
type
TPerson = class
Name: string;
Age: Integer;
end;
TForm1 = class(TForm)
lbPersons: TListBox;
eName: TEdit;
lblName: TLabel;
eAge: TEdit;
lblAge: TLabel;
btnAddUpd: TButton;
procedure FormDestroy(Sender: TObject);
procedure btnAddUpdClick(Sender: TObject);
procedure lbPersonsClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
implementation
{$R *.dfm}
procedure TForm1.btnAddUpdClick(Sender: TObject);
begin
var idx := lbPersons.Items.IndexOf(eName.Text);
var Person: TPerson;
if idx <> -1 then
Person := lbPersons.Items.Objects[idx] as TPerson
else
Person := TPerson.Create;
Person.Name := eName.Text;
Person.Age := StrToInt(eAge.Text);
if idx = -1 then
lbPersons.Items.AddObject(Person.Name, Person);
if eName.CanFocus then
eName.SetFocus;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
for var i := lbPersons.Items.Count - 1 downto 0 do
begin
lbPersons.Items.Objects[i].Free;
lbPersons.Items.Objects[i] := nil;
end;
end;
procedure TForm1.lbPersonsClick(Sender: TObject);
begin
if lbPersons.ItemIndex = -1 then
begin
eName.Text := '';
eAge.Text := '';
end
else
begin
var Person := lbPersons.Items.Objects[lbPersons.ItemIndex] as TPerson;
eName.Text := Person.Name;
eAge.Text := Person.Age.ToString;
end;
end;

https://stackoverflow.com/questions/68702539
复制相似问题