同步不更新 child 表单中的 UI 元素

Synchronize not updating UI elements in a child form

我在 Form1 Unit1.pas 中创建了一个线程 class。然后在那个线程 class 中,我还声明了一个方法来更新同一个 Unit1.pas 的 Form1 class 中的形状颜色。这很好用。

但是当我尝试在 child 表单中执行相同操作时,形状颜色没有改变。有人知道为什么吗?

这是我在测试应用程序中的代码:

Parent unit1.pas 如下所列。 Parent Form1 只有 2 个按钮和 1 个形状。

unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
  ExtCtrls, unit2;


type

      { TMainPortThread }

  TMainPortThread = class(TThread)
  private
    procedure Synchronous;
  protected
    procedure Execute; override;
  public
   // constructor Create(CreateSuspended: boolean);

  end;

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Label1: TLabel;
    Shape1: TShape;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    what:boolean;
  public

  end;

var
  Form1: TForm1;


implementation

{$R *.lfm}

procedure Delay(AMiliSeconds: DWORD);
var
  DW: DWORD;
begin
  DW := GetTickCount64;
  while (GetTickCount64 < DW + AMiliSeconds) and (not Application.Terminated) do
  begin
    // nothing
  end;
end;


{ For Thread }
procedure TMainPortThread.Synchronous;
begin
  writeln('Parents Synchronous Method');
  if Form1.what then
      Form1.Shape1.Brush.Color := clRed
  else
      Form1.Shape1.Brush.Color := clLime;
end;

procedure TMainPortThread.Execute;
var
  i:integer;

begin
  while true do begin
        Delay(500);
        Synchronize(@Synchronous);
        Form1.what := not Form1.what;

  end;
end;

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
var
  settings : TForm2;
begin
     settings := TForm2.Create(Form1);
  settings.Show;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
     TMainPortThread.Create(false);
end;

end.

child Unit2.pas 和Form2。 Form2 只有 1 个按钮和 1 个形状。

unit Unit2;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
  ExtCtrls;

type

    { TMainPortThread }

  TSecondPortThread = class(TThread)
  private
    procedure Synchronous;
  protected
    procedure Execute; override;
  public
   // constructor Create(CreateSuspended: boolean);

  end;


  { TForm2 }

  TForm2 = class(TForm)
    Button1: TButton;
    Label1: TLabel;
    Shape1: TShape;
    procedure Button1Click(Sender: TObject);
  private
     what:boolean;
  public

  end;

var
  Form2: TForm2;


implementation

{$R *.lfm}

procedure Delay(AMiliSeconds: DWORD);
var
  DW: DWORD;
begin
  DW := GetTickCount64;
  while (GetTickCount64 < DW + AMiliSeconds) and (not Application.Terminated) do
  begin
    // nothing
  end;
end;


{ For Thread }
procedure TSecondPortThread.Synchronous;
begin
  writeln('Child Synchronous Method');
  if Form2.what then
      Form2.Shape1.Brush.Color := clRed
  else
      Form2.Shape1.Brush.Color := clLime;
end;

procedure TSecondPortThread.Execute;
var
  i:integer;

begin
  while true do begin
        Delay(500);
        Synchronize(@Synchronous);
        Form2.what := not Form2.what;

  end;
end;



{ TForm2 }

procedure TForm2.Button1Click(Sender: TObject);
begin
    TSecondPortThread.Create(false);
end;


end.

在Form1中,单击按钮后形状颜色在红色和绿色之间交替。然后通过单击另一个按钮打开 Form2 并单击 Form2 上的按钮,形状只保持相同的颜色。没看懂。

如果你想要完整的项目,这里是: https://mega.nz/file/y8oEkbTS#EpsxNL6WhZL5qWvBijqcMD4NsPPn2c70CIsM7jwcHXc


编辑:@Tom 给出了正确答案。

补充一下,因为我想保留新的表单实例创建方法,所以只需删除project.lpr中的自动创建代码,然后在Button1Click创建时使用实际的表单名称。即 Form2.CreateForm()。不要在 Form1 中声明 Form2 的另一个变量实例。

procedure TSecondPortThread.Synchronous; 中,您指的是自动创建的表单 Form2 及其形状。但是,即使创建了 Form2,它也从未显示。

相反,在 procedure TForm1.Button1Click(Sender: TObject); 中,您正在创建并显示类型为 TForm2 的名为 settings 的实例。但是闪烁计时器线程不知道 settings 形式。

一个更正是,因为 Form2 是自动创建的,所以只需将 TForm1.Button1Click() 中的所有代码替换为 Form2.Show