2013-11-28 154 views
1

我試圖創建一個類,它將顯示文本幾秒鐘,然後消失。試圖從ArrayList中刪除元素

我正在使用LWJGL,並在我的主類MetalCLicker中,我有一個循環通過彈出窗口的循環。

  for(PopUp pop: popups){ 
      pop.tick(pop); 
     } 

彈出類:(在蜱方法底部問題) 公共類彈出{

MetalClicker game; 

int x; 
float y, lifetime; 
String line1, line2, line3; 
Color color; 

private UnicodeFont font; 


public PopUp(MetalClicker game, int x, int y, float lifetime, String line1, String line2, String line3, Color color){ 
    this.x = x; 
    this.y = y; 
    this.lifetime = lifetime*game.fps; 
    this.line1 = line1; 
    this.line2 = line2; 
    this.line3 = line3; 
    this.color = color; 
    this.game = game; 


    font = new UnicodeFont(new java.awt.Font ("Vani", Font.BOLD, 12)); 
    font.getEffects().add(new ColorEffect(java.awt.Color.white)); 
    font.addNeheGlyphs(); 
    try { 
     font.loadGlyphs(); 
    } catch (SlickException e) { 
     e.printStackTrace(); 
    } 
} 

public void render(){ 
    font.drawString(x - (line1.length()/2), y, line1, color); 
    font.drawString(x - (line2.length()/2), y+14, line2, color); 
    font.drawString(x - (line3.length()/2), y+28, line3, color); 
} 

public void tick(PopUp pop){ 
    y -= 3/lifetime; 

    lifetime -= 1; 
    if (lifetime == 0) game.popups.remove(pop); //problem resides here 
    else render(); 
} 
} 

程序崩潰時壽命命中0,從而試圖刪除的元素。 把打印之前和之後的刪除線成功打印出的線,所以我現在很困惑:(

我已經在蜱方法,使用這種嘗試,所以我切換到的參數發送實際的元素。

有在控制檯沒有錯誤,但調試告訴我 的ArrayList $ Itr.next()線:831 的ArrayList $ Itr.checkForComodification()線:859 [局部變量不可用]

內螺紋[主]

我會更新後w如果需要,我會提供更多信息,但我無法想出要說些什麼來幫助你,幫助我。

關於如何在我的方法參數中不使用MetalCLicker遊戲的信息會很酷。

回答

1

您嘗試在遍歷列表時刪除元素,從而使迭代器失效。你不能用這個:

for(PopUp pop: popups) { 
    popups.remove(pop); // effectively, due to tick 
} 

甚至,安全的做法是:

for(var i=0, last=popups.size(); i<last; i++) { 
    PopUp pop = popups.get(i); 
    popups.remove(pop); // next "i++" will skip over an item 
} 

但是,您可以使用此:

for(var i=popups.size()-1; i>=0; i--) { 
    PopUp pop = popups.get(i); 
    popups.remove(pop); 
} 

因爲任何清除現在的部分發生數組列表,不會被下一次迭代觸及

+0

另一個更好的解決方案(至少在我看來)是使用迭代器,然後使用'remove()'命令。 (假設集合支持它) –

+0

我不得不不同意,因爲迭代器會進行迭代,而且它的刪除方法會導致令人難以置信的額外開銷,否則這種安全刪除甚至不需要迭代中斷。 –

+0

誠然,你肯定會增加開銷,但你正在變得清晰。 –

0

您無法在集合中循環並直接從其中刪除項目。在這裏你有兩個選擇,你可以將這個集合單獨複製到一個新的循環集合中,或者你可以直接使用集合迭代器並將迭代器作爲參數發送到tick方法,而不是使用foreach,那麼你可以調用集合迭代器的remove方法,它不會拋出這個異常。

所以它要麼改變foreach到:

for(PopUp pop : popups.clone()){ 
    pop.tick(pop); 
} 

或者使用的,而不是一個foreach迭代器:

Iterator<PopUp> iterator = popups.iterator(); 
while (iterator.hasNext()) { 
    PopUp pop = iterator.next(); 
    pop.tick(iterator); 
} 

,並在tick實現:

public void tick(Iterator it){ 
    y -= 3/lifetime; 

    lifetime -= 1; 
    if (lifetime == 0) { 
     it.remove(); 
    } 
    else render(); 
} 

兩者都有大多數效果相同,但我會說第二種選擇更好。