如何自动将 GUI 保存到文件? (范例)
How to automatically save the GUI to file? (Paradigm)
good (and bad) old Delphi 教会了我们 "classic" 构建应用程序的方法,因为我们编写代码的方式 "behind" IDE。
基于这个范例,我前段时间构建了一个库,它允许我使用一行代码 save/load 将 GUI 转换为 INI 文件。
LoadForm(FormName)
砰!而已!没有更多的 INI 文件!
库仅保存 "relevant" 属性。例如,对于 TCheckBox
它只保存它的 Checked
属性 而不是它的 Color
或 Top/Left
。但这已经绰绰有余了。
保存表格没有问题。但是,我在应用程序初始化期间有 "problems"。它们不是问题,但初始化代码不是 nice/elegant.
例如,当我分配 Checkbox1.Checked := True
时,它将触发 OnClick
事件(假设在设计时未选中该复选框)。但是分配 False
值(自然地)不会触发 OnClick
事件。
因此,我必须在 SaveForm(FormName)
之后手动调用 CheckBox1Click(Sender)
以确保 CheckBox1Click
中的任何代码都已初始化。但这引发了另一个问题。 CheckBox1Click(Sender)
在应用程序启动期间可能会被调用两次(一次由 SaveForm
和一次我自己手动调用)。
当然,理论上程序的逻辑应该放在单独的对象中,与GUI分离。但即使我们这样做了,初始化问题仍然存在。您从磁盘加载对象的属性并将它们分配给 GUI。当您将对象中的任何值设置为 Checkbox1
时,它会(或不)调用 CheckBox1Click(Sender)
将值设置回对象。
在应用程序启动时:
procedure TForm.FormCreate (Sender: TObject);
begin
LogicObject.Load(File); // load app logic
Checkbox1.Checked := LogicObject.Checked; // assign object to GUI
end;
procedure TForm.CheckBox1Click(Sender: TObject);
begin
LogicObject.Checked := Checkbox1.Checked;
end;
可能解决方案涉及为表单上的每个控件编写这样的内容:
OldEvent := CheckBox1.OnClick;
CheckBox1.OnClick := Nil;
CheckBox1.Checked := something;
CheckBox1.OnClick := OldEvent;
不优雅。
问题:
你是如何解决这个具体问题的 OR 当 saving/restoring 你的 GUI to/from 磁盘时你的方法是什么?
这是从一开始就在某些组件中困扰我的事情之一。我所知道的有 3 个选项,除了 @David 所说的将 GUI 和业务逻辑分开,这并不总是一个选项。
- 正如您在上面所写,始终取消分配事件,以免触发它们
- 使用非触发事件,例如
OnMouseDown
或 OnMouseUp
- 或者我认为最优雅的类似解决方案
创建一个在初始化期间设置的全局变量 FormPreparing
,并在事件开始时检查其值,如下所示。
procedure TForm.FormCreate (Sender: TObject);
begin
FormPreparing := True;
try
LogicObject.Load(File); // load app logic
Checkbox1.Checked := LogicObject.Checked; // assign object to GUI
finally
FormPreparing := False;
end;
end;
procedure TForm.CheckBox1Click(Sender: TObject);
begin
if FormPreparing then
Exit;
LogicObject.Checked := Checkbox1.Checked;
end;
good (and bad) old Delphi 教会了我们 "classic" 构建应用程序的方法,因为我们编写代码的方式 "behind" IDE。
基于这个范例,我前段时间构建了一个库,它允许我使用一行代码 save/load 将 GUI 转换为 INI 文件。
LoadForm(FormName)
砰!而已!没有更多的 INI 文件!
库仅保存 "relevant" 属性。例如,对于 TCheckBox
它只保存它的 Checked
属性 而不是它的 Color
或 Top/Left
。但这已经绰绰有余了。
保存表格没有问题。但是,我在应用程序初始化期间有 "problems"。它们不是问题,但初始化代码不是 nice/elegant.
例如,当我分配 Checkbox1.Checked := True
时,它将触发 OnClick
事件(假设在设计时未选中该复选框)。但是分配 False
值(自然地)不会触发 OnClick
事件。
因此,我必须在 SaveForm(FormName)
之后手动调用 CheckBox1Click(Sender)
以确保 CheckBox1Click
中的任何代码都已初始化。但这引发了另一个问题。 CheckBox1Click(Sender)
在应用程序启动期间可能会被调用两次(一次由 SaveForm
和一次我自己手动调用)。
当然,理论上程序的逻辑应该放在单独的对象中,与GUI分离。但即使我们这样做了,初始化问题仍然存在。您从磁盘加载对象的属性并将它们分配给 GUI。当您将对象中的任何值设置为 Checkbox1
时,它会(或不)调用 CheckBox1Click(Sender)
将值设置回对象。
在应用程序启动时:
procedure TForm.FormCreate (Sender: TObject);
begin
LogicObject.Load(File); // load app logic
Checkbox1.Checked := LogicObject.Checked; // assign object to GUI
end;
procedure TForm.CheckBox1Click(Sender: TObject);
begin
LogicObject.Checked := Checkbox1.Checked;
end;
可能解决方案涉及为表单上的每个控件编写这样的内容:
OldEvent := CheckBox1.OnClick;
CheckBox1.OnClick := Nil;
CheckBox1.Checked := something;
CheckBox1.OnClick := OldEvent;
不优雅。
问题:
你是如何解决这个具体问题的 OR 当 saving/restoring 你的 GUI to/from 磁盘时你的方法是什么?
这是从一开始就在某些组件中困扰我的事情之一。我所知道的有 3 个选项,除了 @David 所说的将 GUI 和业务逻辑分开,这并不总是一个选项。
- 正如您在上面所写,始终取消分配事件,以免触发它们
- 使用非触发事件,例如
OnMouseDown
或OnMouseUp
- 或者我认为最优雅的类似解决方案
创建一个在初始化期间设置的全局变量 FormPreparing
,并在事件开始时检查其值,如下所示。
procedure TForm.FormCreate (Sender: TObject);
begin
FormPreparing := True;
try
LogicObject.Load(File); // load app logic
Checkbox1.Checked := LogicObject.Checked; // assign object to GUI
finally
FormPreparing := False;
end;
end;
procedure TForm.CheckBox1Click(Sender: TObject);
begin
if FormPreparing then
Exit;
LogicObject.Checked := Checkbox1.Checked;
end;