同步不更新 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
。
我在 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
。