同步而不更新子窗体中的UI元素



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

但当我尝试在儿童形态中做同样的事情时,形状的颜色不会改变。有人知道为什么吗?

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

父单元1.pas如下所示。父窗体1只有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.

子单元2.pas和Form2。Form2只有一个按钮和一个形状。

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);中,您正在创建并显示一个名为settings、类型为TForm2的实例。但是settings形式对于闪烁定时器线程来说是未知的。

一种校正是,由于Form2是自动创建的,所以简单地用Form2.Show替换TForm1.Button1Click()中的所有代码。

最新更新