【发布时间】:2021-08-08 16:10:22
【问题描述】:
在 Windows 10 中的 Delphi 10.4.2 win-32 VCL 应用程序中,我使用简单的 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;
但是,单击列表框项时,我得到随机结果!
EDIT2:在 Andreas 的回答之后,我现在不再释放创建的对象:
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;
我还更改了FormDestroy中ListBox对象的释放:
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;
现在它似乎工作了。谢谢你,安德烈亚斯!
【问题讨论】:
-
使用对象代替记录。然后不需要丑陋的
TObject演员表,因为您实际上是在提供一个对象!这就是它(主要)应该被使用的方式。 -
@AndreasRejbrand 你的意思是,我应该声明一个带有 setter 和 getter 的类而不是记录?记录不是更容易处理吗?一个类不会增加更多不必要的复杂性吗?
-
一个类不需要有getter和setter。而不是
type TTest = record A, B: Integer; c: string; end;,只需执行type TTest = class A, B: Integer; c: string; end;。默认情况下,A和B和c将是公开的。如果您不需要它们,则不需要带有 getter 和 setter 的私有字段和公共属性。是的,记录是值类型,而对象是引用类型(您需要创建和释放它们),但在您的情况下,使用引用类型更方便。此外,您已经在进行分配和释放,尽管是以古老的方式! -
@AndreasRejbrand 我听从了您的建议,使用类而不是记录。但是,当我单击 ListBox 中的一个项目时,我得到的代码大多是随机值:
ThisResizeSettings := TResizeSettings(listboxMultiResize.Items.Objects[listboxMultiResize.ItemIndex]);CodeSite.Send('TformMain.listboxMultiResizeClick: TopValue', ThisResizeSettings.TopValue); -
那你做错了什么。一开始是不要使用不安全的演员表,而是安全的
as演员表。
标签: delphi listbox delphi-10.4-sydney