2013-05-20 61 views
0

我在用新數據更新JPanel時遇到問題。我正在開發一款遊戲,我想要做的事情的基本概念是加載播放器並顯示他保存在JPanel中的項目(設置在盒子佈局中)我正在使用線程和循環來更新玩家項目。這對一個玩家來說很好,但我的遊戲允許用戶可以在其中切換的其他玩家。當我切換到下一個玩家時,我希望他們的細節被加載和更新。這不起作用。在JPanel中顯示正確的信息

這只是代碼的一小部分,但我希望有人能夠看到我的問題。

private JFrame frame; 
private JPanel mainPanel; 
private Box Item1 Item2, Item3; 
static private JPanel centerPanel; 


private boolean playerLoaded; 
private Player currentPlayer; 

private Thread gameThread; 




public void run(){ 

    while (running){ 



     for (Player player:allPlayers){ 
      playerLoaded = false; 
      currentPlayer = player; 
      player.setCurrentTurn(true); 

      while (player.isCurrentTurn()){ 

       if (playerLoaded != true){ 

        loadPlayer(player); 
        loadItems(player); 
        playerLoaded = true; 


       } 

       if ((playerLoaded == true){ 

       updateItems(player); 

       try { 
        Thread.sleep(999); 
       } catch (InterruptedException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } 
       } 

      } 

     } 


     } 
    } 


public void loadPlayer(Player player){ 
jlCurrentPlayer.setText("Player: " + player.getName()); 

} 

public void loadItems(Player player){ 
int count = 1; 

centerPanel = new JPanel(new GridLayout(1,3)); 

for (Item Item : player.getAllItems()){ 

    if (count == 1) { 
    Item1 = Box.createVerticalBox(); 
    Item1.setBorder(BorderFactory.createLineBorder(Color.BLACK)); 
    JLabel jlItem = new JLabel(item.getName()); 
    Item1.add(jlItem); 
    centerPanel.add(Item1); 
    } 
    else if (count ==2){ 
    Item2 = Box.createVerticalBox(); 
    Item2.setBorder(BorderFactory.createLineBorder(Color.BLACK)); 
    JLabel jlItem = new JLabel(item.getName()); 
    Item2.add(jlItem); 
    centerPanel.add(Item2); 
    } 
    else if (count ==3){ 
    Item3 = Box.createVerticalBox(); 
    Item3.setBorder(BorderFactory.createLineBorder(Color.BLACK)); 
    JLabel jlItem = new JLabel(item.getName()); 
    Item3.add(jlItem); 
    centerPanel.add(Item3); 
    } 

    mainPanel.add(centerPanel,BorderLayout.CENTER); 

    count++; 
} 

} 


    public void updateItemstats(Player player){ 
int count = 1; 
if (player.isCurrentTurn()){ 
for (Item item : player.getAllItems()){ 

    if ((count == 1) && (player.isCurrentTurn())) { 
     Item1.add(Box.createVerticalGlue()); 
     Item1.add(new JLabel("Value: " + item.getstats().getValue())); 
     Item1.add(new JLabel("Quality: " + item.getStats().getQuality())); 
    } 
    else if (count ==2){ 
     Item2.add(Box.createVerticalGlue()); 
     Item2.add(new JLabel("Value: " + item.getstats().getValue())); 
     Item2.add(new JLabel("Quality: " + item.getStats().getQuality())); 

    } 
    else if (count ==3){ 
     Item3.add(Box.createVerticalGlue()); 
     Item3.add(new JLabel("Value: " + item.getstats().getValue())); 
     Item3.add(new JLabel("Quality: " + item.getStats().getQuality())); 

    } 
count++; 

} 
} 
} 

JButton jbNext = new JButton("Next Player");  

jbNext.addActionListener(new ActionListener() { 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      currentPlayer.setCurrentTurn(false); 

     } 
    }); 

對於我的主框架我使用的是邊框佈局。當我切換球員時發生的事情基本上是更新的信息有時是球員1和2的混合。

值25 質量60

值50 質量20.

另外,如果播放器1具有1項和玩家2具有3項和我從播放器2切換到1有時播放器1將具有玩家2的所有物品而不是他自己的物品。

我認爲這可能是一個Item1 2和3面板的問題,所以我試圖刪除他們在下一個玩家btn點擊,但這只是造成了一個例外。這可能仍是問題,我可能無法正確刪除它們。

任何人都可以幫助我嗎?

回答

1

您應該在下一個玩家動作偵聽器中爲下一個玩家撥打setCurrentTurn(true)

您是否已將currentPlayer變量設置爲Playervolatile?重要提示:Player.java中的private Player currentPlayerprivate boolean currentPlayer必須是volatile。 (看一看http://javamex.com/tutorials/synchronization_volatile.shtml

此外,使用監視器和wait(),而不是Thread.sleep這樣你可以使用notify()喚醒等待Thread

以下是您的代碼的一些建議,但請注意,您將不得不做更多事情(例如Player.java類中未顯示的內容)。

volatile List<Player> players = ...; // load your list of Player 
volatile int currentPlayerIndex = 0; 
volatile Player currentPlayer = null; 
private final Object WAIT_MONITOR = new Object(); // yes, 'new Object()' ! 
[...] 
public void run() throws InterruptedException { 
    playerLoop: 
    while(programRunning) { // maybe while(true) 
     synchronized (WAIT_MONITOR) { 
      loadPlayer(currentPlayer); 
      loadItems(currentPlayer); 

      updateItems(currentPlayer); 
      WAIT_MONITOR.wait(1000); 
     } 
    } 
} 

[...] 

JButton jbNext = new JButton("Next Player");  

jbNext.addActionListener(new ActionListener() { 
    @Override 
    public void actionPerformed(ActionEvent e) { 
     synchronized(WAIT_MONITOR) { // this causes that the contents of run() and this method do not run at the same time. 
      currentPlayer.setCurrentTurn(false); 
      if(players.size() > currentPlayerIndex + 1) // don't use >= 
       currentPlayerIndex++; 
      else 
       currentPlayerIndex = 0; // reset at the end of the list 
      currentPlayer = players.get(currentPlayerIndex); 
      currentPlayer.setCurrentTurn(true); 
      WAIT_MONITOR.notifyAll(); // that causes the wait() method above to be continued. 
     } 
    } 
}); 
+0

嘿感謝您的回覆,setCurrentTurn True不會工作他們(我試過了),我將播放器變量設置爲易失性,也沒有幫助。有時框架顯示正確的信息,但往往不是它的全部搞砸......可能是線程的東西,因爲它等待幾秒鐘,它可能不會馬上得到消息更改播放器..也許... – whiteElephant

+0

@whiteElephant請看看我編輯的答案。 –

+0

感謝您的更新,非常有幫助。我快到了。我的球員ID從0開始並從那裏上升。第一個玩家id = 0,第二個玩家= 1等等。所以我不確定現在的問題是什麼,但是我得到的索引超出範圍例外。我正在使用你的代碼,除了通過告訴應用程序從索引0開始啓動第一個玩家以外,如果我玩2個玩家它會完全更改爲下一個玩家,但是當我再次單擊時,我得到的索引超出範圍異常。你看不出有什麼不對嗎? – whiteElephant