0

JPanels を新しいデータで更新できません。私はゲームに取り組んでいます。私がやろうとしていることの基本的な概念は、プレイヤーをロードし、彼が保持するアイテムを JPanel に表示することです (ボックス レイアウトに設定)。スレッドとループを使用して更新します。プレイヤーアイテム。これは 1 人のプレーヤーには問題なく機能しますが、私のゲームでは、ユーザーが切り替えることができる追加のプレーヤーを使用できます。次のプレーヤーに切り替えるときに、その詳細をロードして更新する必要があります。これはうまくいきません。

これはコードのスニペットにすぎませんが、誰かが私の問題を見ることができることを願っています。

    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);

        }
    });

私のメイン フレームでは、Border Layout を使用しています。プレーヤーを切り替えると何が起こるかというと、基本的に更新された情報は、プレーヤー 1 と 2 の混合である場合があります。

価値 25 品質 60

価値 50 品質 20.

さらに、プレイヤー 1 が 1 つのアイテムを持ち、プレイヤー 2 が 3 つのアイテムを持っていて、プレイヤー 2 から 1 に切り替えると、プレイヤー 1 が自分のアイテムではなくプレイヤー 2 のアイテムをすべて持つことがあります。

Item1 2 と 3 のパネルに問題があるのではないかと思ったので、次のプレーヤーのボタン クリックでそれらを削除しようとしましたが、例外が発生しました。これはまだ問題である可能性があり、それらを正しく削除していない可能性があります。

誰かがこれで私を助けることができますか?

4

1 に答える 1

1

setCurrentTurn(true)次のプレーヤー アクション Listener で次の Player を呼び出す必要があります。

currentPlayerに変数を設定しましPlayervolatileか? 重要:private Player currentPlayerと の の両方がprivate boolean currentPlayerであるPlayer.java必要がありますvolatile。( http://javamex.com/tutorials/synchronization_volatile.shtmlをご覧ください)

また、 Monitor を使用し、wait()その代わりにWaiting をウェイクアップするために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.
        }
    }
});
于 2013-05-20T22:20:34.400 に答える