【发布时间】:2017-03-24 10:27:02
【问题描述】:
以下错误仅在 MacOS 下测试时发生。在 Windows 下它似乎可以工作。我正在尝试将字符串的动态列表显示到 TPanel 中,每个在它自己的 TPanel 中。字符串列表保存在 TStringList 对象中,每次添加或删除新字符串时,我都会调用一个方法来通过清除存在的内容来更新显示,然后重新构建可视组件。更新面板显示方式如下:
procedure TTestsScreen.UpdatePanelDisplay3;
var
i : Integer;
myPanel : TPanel;
myLabel : TLabel;
myImage : TImage;
begin
//dispose of existig entities
for i := (Length(search_entities_labels) - 1) downto 0 do
begin
search_entities_labels[i].Free;
search_entities_labels[i]:= nil;
end;
for i := (Length(search_entities_images) - 1) downto 0 do
begin
search_entities_images[i].Free;
search_entities_images[i]:= nil;
end;
for i := (Length(search_entities_panels) - 1) downto 0 do
begin
search_entities_panels[i].Free;
search_entities_panels[i]:= nil;
end;
//adjust dynamic arrays
SetLength(search_entities_images,main_search_entities_string_list.Count);
SetLength(search_entities_labels,main_search_entities_string_list.Count);
SetLength(search_entities_panels,main_search_entities_string_list.Count);
//rebuild
for i := 0 to main_search_entities_string_list.Count-1 do
begin
myPanel:= TPanel.Create(Self);
myPanel.Parent := Panel1;
myPanel.Height:= 30;
myPanel.Width:= Panel1.Width;
myPanel.Position.X:= 0;
myPanel.Position.Y:= i*30;
search_entities_panels[i]:= myPanel;
//
myLabel:= TLabel.Create(Self);
myLabel.Parent:= myPanel;
myLabel.Text:= main_search_entities_string_list[i];
myLabel.Width:= (3*myPanel.Width) / 4;//display left
search_entities_labels[i]:= myLabel;
//
myImage:= TImage.Create(Self);
myImage.Parent:= myPanel;
myImage.Tag:= i;
myImage.Width:= 15;
myImage.Height:= 15;
myImage.Position.X:= myPanel.Width - myImage.Width;//display right
myImage.MultiResBitmap.Assign(AppResources.delete_white_image.MultiResBitmap);
myImage.OnClick:= DeleteSearchEntity;
search_entities_images[i]:= myImage;
end;
//
Panel1.Height:= 30 * main_search_entities_string_list.Count;
end;
我正在向面板中添加新元素,如下所示:
procedure TTestsScreen.AddClick(Sender: TObject);
begin
main_search_entities_string_list.Add(DateTimeToStr(now));
UpdatePanelDisplay3;
end;
添加过程正常,没有错误。问题是当我尝试删除这样的元素时
procedure TTestsScreen.DeleteSearchEntity(Sender: TObject);
begin
main_search_entities_string_list.Delete((Sender as TImage).Tag);
UpdatePanelDisplay3;
end;
我随机得到
Runtime error 231
或
Exception EAccessViolation in module TestApp at 00039F33.
Access violation at address 00E7BBBC, accessing address 00000158.
Runtime error 0 at 00039F33
在我正在做的 FormCreate 事件中
procedure TTestsScreen.FormCreate(Sender: TObject);
begin
SetLength(search_entities_labels,0);
SetLength(search_entities_images,0);
SetLength(search_entities_panels,0);
main_search_entities_string_list:= TStringList.Create;
end;
数组被声明为
search_entities_labels : array of TLabel;
search_entities_images : array of TImage;
search_entities_panels : array of TPanel;
【问题讨论】:
-
如果不使用大小数组,而是尝试使用泛型...例如 TObjectList
,会怎样?这将大大简化代码。但我认为你真正的问题是你想从它的一个事件处理程序中释放一个视觉组件......这是一个禁忌。 OnClick 事件处理程序是破坏事件发送者的一个非常错误的地方。 -
@Frazz,刚刚尝试将 UpdatePanelDisplay3 推迟到手动触发的事件(在从 TStringList 中删除之后)并且错误不再发生。自动进行视觉删除的最佳方法是什么?谢谢。
-
最好的办法是使用事件处理程序将删除消息入队,然后在有时间的时候在UI线程中处理该消息。
-
@Frazz,你能把这个作为答案发布吗?
标签: delphi firemonkey