我在Firemonkey中使用TListBox
,在动态显示/隐藏项目时我遇到了一个奇怪的问题。这包括Delphi XE7和XE8。设置时,表单顶部有一个TPopupBox
,用户可在其中选择列出的项目之一。根据选择的内容,TListBox
应仅显示某些TListBoxItem
,并隐藏其余内容。部分内容包括在不可见时将每个列表项高度调整为0(否则会在项目之间留下难看的空隙)。
问题是非常随机且自发地(没有模式),选择此TPopupBox
中的项目(调用OnChange
修改可见性),在未知点产生EArgumentOutOfRangeException
。代码在调用System.Generics.Collections.TListHelper.SetItemN()
的第一行的CheckItemRangeInline(AIndex);
处中断,其中只是:
procedure TListHelper.CheckItemRangeInline(AIndex: Integer);
begin
if (AIndex < 0) or (AIndex >= FCount) then
raise EArgumentOutOfRangeException.CreateRes(@SArgumentOutOfRange);
end;
异常继续一遍又一遍地提出,没有结束(从4开始)。当我使用调试器介入时,我永远无法让它发生。
这里使用了几个常用程序来控制项目可见性:
//lstTrans = TListBox
//Iterates through all items and hides everything
procedure TfrmMain.HideTransItems;
var
X: Integer;
begin
for X := 0 to lstTrans.Count-1 do begin
lstTrans.ListItems[X].Visible:= False;
end;
end;
//Sets height of visible items to 42, invisible items to 0
procedure TfrmMain.ResetTransHeights;
var
X: Integer;
LI: TListBoxItem;
begin
for X := 0 to lstTrans.Count-1 do begin
LI:= lstTrans.ListItems[X];
if LI.Visible then
LI.Height:= 42
else
LI.Height:= 0;
end;
end;
然后,在TPopupBox
:
//cboTrans = TPopupBox
procedure TfrmMain.cboTransChange(Sender: TObject);
procedure E(AItem: TListBoxItem);
begin
AItem.Visible:= True;
end;
begin
HideTransItems; //Make all list items invisible
case cboTrans.ItemIndex of
0: begin
E(lbSomeListBoxItem);
E(lbSomeOtherItem);
//More calls to "E"
end;
1: begin
E(lbSomeListBoxItem2);
//More calls to "E"
end;
//More indexes
end;
ResetTransHeights; //Adjust visible list item heights to be seen
end;
(完整的程序只是很多完全相同类型的调用,在此处发布的内容太多了)
TPopupBox
位于TListBox
TListBoxItem
都有一个或两个控件(但显示/隐藏哪些控件并不重要)TPopupBox
中的项目可能会有效,但下一次为什么我会收到此异常,我该如何解决?
答案 0 :(得分:1)
为什么我会收到此异常,我该如何解决?
你知道为什么要收到它。您正在访问索引位于有效范围之外的数组。
问题在于该指数在哪里。如果您无法轻松重现,则需要进行调试以收集诊断信息。在Windows上,您将使用像madExcept这样的工具来收集信息。最有用的是导致错误的调用堆栈。
如果您没有使用madExcept或类似工具,请使用跟踪日志记录。检测您的代码,以便它记录允许您确定列表的哪个访问超出范围的信息。在缩小搜索范围时,您可能最终会对此进行迭代。
最后,一旦确定哪个代码导致错误,通常问题就会变得明显。
答案 1 :(得分:0)
当我设置TListBoxItem的高度时,我遇到了同样的问题。 该问题仅发生在我更改 所选 项目的高度时。我实现了Jerry Dodge's解决方案,将高度设置为0.01而不是0来解决问题。
德尔福柏林代码
{Delphi Berlin}
ItemIndex := 0;
Item := ListBox.ItemByIndex(ItemIndex);
Height := Item.Height;
FloatAnimation := TFloatAnimation.Create(nil);
FloatAnimation.Parent := Item;
FloatAnimation.PropertyName := 'height'
FloatAnimation.StartValue := Height;
FloatAnimation.StopValue := 0.01; {Setting to 0 causes "Argument out of range" if the item is selected}
FloatAnimation.Start;