【问题标题】:Displaying correct information in JPanel在 JPanel 中显示正确的信息
【发布时间】:2013-05-20 22:15:01
【问题描述】:

我在使用新数据更新 JPanel 时遇到问题。我正在开发一款游戏,我正在尝试做的基本概念是加载玩家并在 JPanel 中显示他持有的项目(以框布局设置)我正在使用线程和循环来更新播放器物品。这对一个玩家来说效果很好,但我的游戏允许用户可以在其他玩家之间切换。当我切换到下一个播放器时,我希望加载和更新他们的详细信息。这行不通。

这只是代码的 sn-p,但我希望有人能够看到我的问题。

    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 单击时将其删除,但这只是导致了异常。这很可能仍然是问题,我可能没有正确删除它们。

有人可以帮我解决这个问题吗?

【问题讨论】:

    标签: java multithreading swing


    【解决方案1】:

    你应该在下一个玩家动作监听器中为下一个玩家调用setCurrentTurn(true)

    您是否将Player 中的currentPlayer 变量设置为volatile?重要提示:Player.java 中的private Player currentPlayerprivate boolean currentPlayer 都必须是volatile。 (看看http://javamex.com/tutorials/synchronization_volatile.shtml

    另外,使用 Monitor 和 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.
            }
        }
    });
    

    【讨论】:

    • 嘿,感谢您的回复,setCurrentTurn True 无法正常工作(我试过了),我将 player 变量设置为 volatile,但这也无济于事。有时框架会显示正确的信息,但通常情况下它都搞砸了...可能与线程有关,因为它会等待几秒钟,它可能无法立即获得消息以更改播放器...也许...
    • 感谢更新,非常有帮助。我快到了。我的玩家 ID 从 0 开始并从那里上升。第一个玩家 id = 0,第二个玩家 = 1 等等。所以我不确定目前的问题是什么,但我得到了一个超出范围异常的索引。我正在使用上面的代码,除了通过告诉应用程序从索引 0 开始来启动第一个玩家之外,如果我与 2 个玩家一起玩它会完美地更改为下一个玩家但是当我再次单击时,我得到索引超出范围异常.我看不出有什么问题吗?
    • @whiteElephant 是的,对不起。我忘记了 +1
    • 哈哈也想通了。非常感谢您的帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多