k0t*_*0tt 0 delphi free panel self button
我有一个 TScrollBox,里面有一堆 TPanel,还有一些在运行时生成的 TButton。我需要在单击一个 TButton 时删除 TPanel,但在 OnClick 中执行此操作会导致访问冲突......
procedure TMainForm.ButanClick(Sender: TObject);
var
vParentPanel: TPanel;
begin
if (string(TButton(Sender).Name).StartsWith('L')) then
begin
TButton(Sender).Caption := 'YARE YARE DAZE';
end
else
begin
vParentPanel := TPanel(TButton(Sender).GetParentComponent());
TheScrollBox.RemoveComponent(vParentPanel);
vParentPanel.Destroy();
// access violation but the panel is removed
end;
end;
procedure TMainForm.Button3Click(Sender: TObject);
var
i: Integer;
vPanel: TPanel;
vButton: TButton;
begin
for i := 0 to 20 do
begin
vPanel := TPanel.Create(TheScrollBox);
vPanel.Align := alTop;
vPanel.Parent := TheScrollBox;
vButton := TButton.Create(vPanel);
vButton.Align := alLeft;
vButton.Parent := vPanel;
vButton.Name := 'L_butan' + IntToStr(i);
vButton.OnClick := ButanClick;
vButton := TButton.Create(vPanel);
vButton.Align := alRight;
vButton.Parent := vPanel;
vButton.Name := 'R_butan' + IntToStr(i);
vButton.OnClick := ButanClick;
end;
end;
Run Code Online (Sandbox Code Playgroud)
您无法从的事件内部安全地销毁父级TPanel(或自身) 。事件处理程序退出后, VCL 仍然需要访问/一段时间。因此,您需要将销毁延迟到处理程序退出之后。最简单的方法是使用来调用,例如:TButtonTButtonOnClickTPanelTButtonTThread.ForceQueue()TObject.Free()TPanel
procedure TMainForm.ButanClick(Sender: TObject);
var
vButton: TButton;
begin
vButton := TButton(Sender);
if vButton.Name.StartsWith('L') then
begin
vButton.Caption := 'YARE YARE DAZE';
end
else
begin
TThread.ForceQueue(nil, vButton.Parent.Free);
end;
end;
Run Code Online (Sandbox Code Playgroud)
意志在毁灭过程中将TPanel自己从其中移除。TScrollBox您不需要手动处理该步骤。