请有人知道,为什么我会收到运行时错误:
RangeError: Error #1125: The index 0 is out of range 0.
........
at Popup/update()[Popup.mxml:80]
at PopupTest/showPopup()[PopupTest.mxml:45]
at PopupTest/___btn_click()[PopupTest.mxml:52]
调用函数时:
private function showPopup(event:MouseEvent):void {
_popup.update(new Array('Pass' ,
'6♠', '6♣', '6♦', '6♥', '6 x',
'7♠', '7♣', '7♦', '7♥', '7 x',
'8♠', '8♣', '8♦', '8♥', '8 x',
'9♠', '9♣', '9♦', '9♥', '9 x',
'10♠', '10♣', '10♦', '10♥', '10 x'), true, 80);
}
好像我的_list根本没有条目(但为什么?我确实指定 _data.source = args ),因此 _list.ensureIndexIsVisible(0)调用会在第80行失败:
<?xml version="1.0" encoding="utf-8"?>
<s:Panel xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
width="220" height="200"
initialize="init(event)">
<fx:Script>
<![CDATA[
import mx.collections.ArrayList;
import mx.events.FlexEvent;
import mx.utils.ObjectUtil;
private static const FORCE:uint = 20;
[Bindable]
private var _data:ArrayList = new ArrayList();
private var _timer:Timer = new Timer(1000, 120);
private function init(event:FlexEvent):void {
_timer.addEventListener(TimerEvent.TIMER, timerUpdated);
_timer.addEventListener(TimerEvent.TIMER_COMPLETE, timerCompleted);
}
public function close():void {
_timer.reset();
_data.source = null;
visible = false;
}
private function timerUpdated(event:TimerEvent=null):void {
var seconds:int = _timer.repeatCount - _timer.currentCount;
title = 'Your turn! (' + seconds + ')';
// show panel for cards too
if (seconds < FORCE)
visible = true;
}
private function timerCompleted(event:TimerEvent=null):void {
title = 'Your turn!';
close();
}
public function update(args:Array, bidding:Boolean, seconds:int):void {
if (seconds <= 0) {
close();
return;
}
// nothing has changed
if (ObjectUtil.compare(_data.source, args, 0) == 0)
return;
_data.source = args;
if (args == null || args.length == 0) {
close();
return;
}
if (seconds < FORCE || bidding)
visible = true;
_timer.reset();
title = 'Your turn! (' + seconds + ')';
_list.ensureIndexIsVisible(0); // the line 80
_timer.repeatCount = seconds;
_timer.start();
}
]]>
</fx:Script>
<s:VGroup paddingLeft="10" paddingTop="10" paddingRight="10" paddingBottom="10" gap="10" width="100%" height="100%">
<s:List id="_list" dataProvider="{_data}" width="100%" height="100%" fontSize="24" itemRenderer="RedBlack" />
</s:VGroup>
</s:Panel>
答案 0 :(得分:1)
原因
您正在添加新阵列,但是List会根据该阵列中的项目开始创建ItemRenderers。这需要一些时间并且异步发生。在此期间,您说“显示项目1”,但项目1的ItemRenderer尚不存在。它很快就会发生,但现在不行。这就是你得到indexoutofrange错误的原因。
解决方案
在调用该方法之前,您必须确保List已完成创建ItemRenderers。解决这种情况的最简单方法 - 尽管绝对不是最干净的 - 是通过使用臭名昭着的callLater()等到下一个渲染周期。
callLater(_list.ensureIndexIsVisible, [0]);
这主要是说:等待下一个渲染周期,然后使用参数ensureIndexIsVisible()
在_list
上调用0
。
(旁注:如果你真的只想要索引0,那么整个事情就毫无意义了,因为我认为List无论如何都会在其数据提供者改变时滚动到顶部)
更清洁的解决方案
您可以在列表中收听RendererExistenceEvent#RENDERER_ADD事件。每当将新的ItemRenderer添加到列表中并且它在List,数据和ItemRenderer本身中保存对项目索引的引用时,将调度此方法。但是在你的情况下我们只需要'索引'。每当在索引0处添加ItemRenderer时,我们将滚动回到顶部:
_list.addEventListener(RendererExistenceEvent.RENDERER_ADD, onRendererAdded);
private function onRendererAdded(event:RendererExistenceEvent):void {
if (event.index == 0) myList.ensureIndexIsVisible(0);
}
当添加第一个ItemRenderer时,这将立即滚动到顶部,并且不需要等到所有这些都准备就绪。