あなたは複数回呼び出され繰り返さコード内たActionListenerには、追加している、とこれは、ボタンを押したときにアクションが何度も呼び出される原因となります。
public void run() {
a = true;
// **************************************
// this add ActionListener gets called with every creation
// of a new Thread, and then calling .start() on the Thread
attack1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
healthleft = healthleft - 100;
}
});
// **************************************
// this code does not belong in an event-driven program
do {
healthleftbl.setText(healthleft + "/" + health);
if (healthleft <= 0) {
page.show(game, "map");
break;
}
System.out.println(healthleft);
} while (turn.getState() != null);
}
これを行わないでください。ターン中ではなく、プログラムのセットアップ中にActionListenersを一度追加してください。また、あなたのwhile (true)
ループは、イベントドリブンのプログラムに属しておらず、代わりに、プログラムの動作(ユーザーの入力に対する応答)がプログラムの状態に基づいて変化する状態パターンでコードをパターン化する必要があります。例えば
:
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.*;
import javax.swing.event.SwingPropertyChangeSupport;
public class Temp2 extends JPanel {
private CardLayout cardLayout = new CardLayout();
private GamePanel gamePanel = new GamePanel(this);
private IntroPanel introPanel = new IntroPanel(this);
public Temp2() {
setLayout(cardLayout);
add(introPanel, IntroPanel.class.getName());
add(gamePanel, GamePanel.class.getName());
}
public void showCard(String name) {
cardLayout.show(this, name);
}
private static void createAndShowGui() {
Temp2 mainPanel = new Temp2();
JFrame frame = new JFrame("Temp2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
@SuppressWarnings("serial")
class GamePanel extends JPanel {
private static final int PREF_W = 400;
private static final int PREF_H = 350;
public static final int DAMAGE_AMOUNT = 100;
private Temp2 temp2;
private Player2 player2 = new Player2();
private JLabel statusLabel = new JLabel();
public GamePanel(Temp2 temp2) {
this.temp2 = temp2;
player2.addPropertyChangeListener(Player2.HEALTH, new PlayerListener());
JPanel statusPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 5, 5));
statusPanel.add(new JLabel("Health"));
statusPanel.add(statusLabel);
displayHealth();
JPanel battlePanel = new JPanel(new GridBagLayout());
battlePanel.add(new JButton(new BattleAction("Battle", KeyEvent.VK_B)));
setLayout(new BorderLayout());
add(statusPanel, BorderLayout.PAGE_START);
add(battlePanel, BorderLayout.CENTER);
}
private void displayHealth() {
String healthText = String.format("%03d/%03d", player2.getHealth(), Player2.MAX_HEALTH);
statusLabel.setText(healthText);
}
public void reset() {
player2.setHealth(Player2.MAX_HEALTH);
temp2.showCard(IntroPanel.class.getName());
}
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private class BattleAction extends AbstractAction {
public BattleAction(String name, int mnemonic) {
super(name);
putValue(MNEMONIC_KEY, mnemonic);
}
@Override
public void actionPerformed(ActionEvent e) {
int health = player2.getHealth() - DAMAGE_AMOUNT;
player2.setHealth(health);
}
}
private class PlayerListener implements PropertyChangeListener {
@Override
public void propertyChange(PropertyChangeEvent evt) {
int health = (int) evt.getNewValue();
displayHealth();
if (health <= 0) {
reset();
}
}
}
}
@SuppressWarnings("serial")
class IntroPanel extends JPanel {
private Temp2 temp2;
public IntroPanel(Temp2 temp2) {
this.temp2 = temp2;
setLayout(new GridBagLayout());
add(new JButton(new GoToBattleAction("Go To Battle", KeyEvent.VK_G)));
}
private class GoToBattleAction extends AbstractAction {
public GoToBattleAction(String name, int mnemonic) {
super(name);
putValue(MNEMONIC_KEY, mnemonic);
}
@Override
public void actionPerformed(ActionEvent e) {
temp2.showCard(GamePanel.class.getName());
}
}
}
class Player2 {
// make health a "bound property" by using property change support and listeners
public static final String HEALTH = "health";
public static final int MAX_HEALTH = 800;
private SwingPropertyChangeSupport pcSupport = new SwingPropertyChangeSupport(this);
private int health;
public Player2() {
this.health = MAX_HEALTH;
}
public int getHealth() {
return health;
}
// notify all listeners if health changes
public void setHealth(int health) {
int oldValue = this.health;
int newValue = health;
this.health = health;
pcSupport.firePropertyChange(HEALTH, oldValue, newValue);
}
// allow outside code to listen for changes to all bound properties
// should also have the associated remove listener methods too
public void addPropertyChangeListener(PropertyChangeListener listener) {
pcSupport.addPropertyChangeListener(listener);
}
public void addPropertyChangeListener(String name, PropertyChangeListener listener) {
pcSupport.addPropertyChangeListener(name, listener);
}
}
参照吊りCの[検出/修正コードブロックの括弧を失う](http://meta.stackexchange.com/q/251795/155831)私はもはや悩まされることのない問題を解決する。 –
回答を編集してください –
私は、イベント駆動の州主導コードの例を示す新しいプログラムを作成しました。真のループが見つかるまではありません。 –