如何自动将 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 属性 而不是它的 ColorTop/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 和业务逻辑分开,这并不总是一个选项。

  1. 正如您在上面所写,始终取消分配事件,以免触发它们
  2. 使用非触发事件,例如 OnMouseDownOnMouseUp
  3. 或者我认为最优雅的类似解决方案

创建一个在初始化期间设置的全局变量 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;