为什么我的Swing计划仍在推进?

时间:2013-06-23 19:51:04

标签: java swing actionlistener ioexception dice

所以我的程序使用了连接了actionListeners的JButtons,但是当程序遇到某个应该等待某个动作执行的点时,它会跳过等待的,然后继续。我想知道是否由于没有抛出IOException,但如果我抛出它,它只会返回一堆错误,这会造成巨大的混乱。

是的,我知道我正在使用swing来混合命令行。那是因为它从命令行开始,现在我正在摆动它。

有人能指出一种更简单的解决方法吗?

这是我的代码:

public static void choiceRerollDice() {
            if (!canRerollDiceOne && !canRerollDiceTwo && !canRerollDiceThree && !canRerollDiceFour && !canRerollDiceFive) {
            System.out.println("Sorry, but you may not reroll any more dice...");
            displayDiceValues();
            System.exit(0);
        }
        else {
    System.out.println("Would you like to reroll any (more) dice? (yes/no)");
            area = "choiceReroll";
            }
}

public static void rerollChoice(String choiceReroll) {
    switch (choiceReroll) {
                case "yes":
                    rerollDice();
                    break;
                case "no":
                    //endTurn();
                    displayDiceValues();
                    f.validate();
                    f.repaint();
                    //calculatePlayer1Score();
                    //System.out.println("Thank you for playing!");
                    //System.out.println("Goodbye!");
                    System.exit(0);
                    break;
                default:
                    invalidInput();
    }
}

public static void rerollDice() {
    Scanner is = new Scanner(System.in);
    System.out.println("Which dice would you like to reroll? (Click the box under the dice!)");        
    rollSel = is.next();
    switch (rollSel) {
        case "roll":
        if (willRerollDiceOne) {
            if (canRerollDiceOne) {
                diceOne = 0;
                rollDiceOne();
                canRerollDiceOne = false;
                box1.setEnabled(false);
            }
            else {
                System.out.println("error");
            }
        }

        else {
        }
        if (willRerollDiceTwo) {
            if (canRerollDiceTwo) {
            diceTwo = 0;
            rollDiceTwo();
            canRerollDiceTwo = false;
            box2.setEnabled(false);
            }
            else {
                System.out.println("error");
            }
        }
        else {
        }
        if (willRerollDiceThree) {
            if (canRerollDiceThree) {
            diceThree = 0;
            rollDiceThree();
            canRerollDiceThree = false;
            box3.setEnabled(false);
            }
        }
        else {
        }
        if (willRerollDiceFour) {
            if (canRerollDiceFour) {
            diceFour = 0;
            rollDiceFour();
            canRerollDiceFour = false;
            box4.setEnabled(false);
            }
        }
        else {
        }
        if (willRerollDiceFive) {
            if (canRerollDiceFive) {
            diceFive = 0;
            rollDiceFive();
            canRerollDiceFive = false;
            box5.setEnabled(false);
            }
        }
        else {
        }
        box1.setSelected(false);
        box2.setSelected(false);
        box3.setSelected(false);
        box4.setSelected(false);
        box5.setSelected(false);
        f.validate();
        f.repaint();
            break;
        default:
            System.out.println("Error...");
            break;
    }
    choiceRerollDice();
}

以下是JButtons:

public static JButton textYes = new JButton("Yes");
public static JButton textNo = new JButton("No");

对于actionListeners:

      textYes.addActionListener(this);
      textNo.addActionListener(this);

actionPerformed():

        if ("choiceReroll".equals(area)) {
            if(e.getSource() == textYes){
                rerollChoice("yes");
            }
            if(e.getSource() == textNo){
                rerollChoice("no");
            }
        }

但不是停下来等待输入:

        else {
    System.out.println("Would you like to reroll any (more) dice? (yes/no)");
            area = "choiceReroll";
            }

它继续到rerollDice()

有什么想法吗?

1 个答案:

答案 0 :(得分:4)

一般建议:

  • 由于你已经摆脱了大多数使用扫描仪(对你有用!)和阻塞while (true)循环,目前你不需要使用后台线程。我会摆脱它,只在需要时使用它。
  • 你的课堂庞大而且笨重,这使得我们(并且可能对你来说)很难遵循所包含的逻辑。这是重构代码的一个原因,将代码分解为组成类,每个类都有自己的责任。
  • 通过这样做,您将被迫使用非静态字段和方法,并消除大部分静态使用 - 非常 好事。< / LI>
  • 同样使用数组和列表(例如ArrayLists)将帮助您消除冗余代码,从而使调试和修改变得更加容易。

具体建议:

  • 您的程序逻辑只执行您要求它执行的操作。在代码中添加更多println语句以查看我的意思。如果你这样做:

在actionPerformed中:

        if ("choiceReroll".equals(area)) {
           System.out.println("choiceReroll equals area");
           if (e.getSource() == textYes) {
              System.out.println("source is textYes");
              rerollChoice("yes");
           }
           if (e.getSource() == textNo) {
              rerollChoice("no");
           }
        }

当按下textYes按钮时,你会看到调用rerollChoice(“yes”)。

继续用println喷洒你的代码,看看我的意思。可能会有更具体的记录。或者更好 - 学会使用然后使用调试器。


修改

例如,这是一个稍微过长的示例程序,它显示了我的意思。请注意,它由几个类和枚举组成,后者用于保存对象的“状态”值。

好的,但是说真的,到目前为止,这是我还写的最棒的骰子游戏程序。哈!

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.RenderingHints;
import java.awt.Stroke;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

import javax.swing.*;
import javax.swing.border.Border;

/**
 * DiceGame.java
 * previously called Greed2.java
 * http://stackoverflow.com/questions/17264671/why-is-my-swing-program-still-advancing
 * @author Pete
 * 6/24/2013
 */
public class DiceGame {

   private static void createAndShowGui() {
      DicePanel mainPanel = new DicePanel();

      JFrame frame = new JFrame("Dice Game");
      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(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

@SuppressWarnings("serial")
class DicePanel extends JPanel {
   private static final String FIRST_ROLL_STATUS_TEXT = "Please select die to re-roll and press Second Roll";
   private static final String RESET_STATUS_TEXT = "Please press the First Roll Button";
   private static final String SECOND_ROLL_STATUS_TEXT = "Please press the Reset Button";
   private Die[] dieArray = new Die[5];
   private GameState gameState = GameState.FIRST_ROLL;
   private JButton rollButton = new JButton();
   private JButton exitButton = new JButton();
   private JTextArea messageArea = new JTextArea(20, 60);
   private Map<GameState, Action> rollActionMap = new HashMap<>();
   private JLabel statusLabel = new JLabel("  ");

   public DicePanel() {
      rollActionMap.put(GameState.FIRST_ROLL, new RollAction(this, GameState.FIRST_ROLL));
      rollActionMap.put(GameState.SECOND_ROLL, new RollAction(this, GameState.SECOND_ROLL));
      rollActionMap.put(GameState.RESET, new RollAction(this, GameState.RESET));

      exitButton.setAction(new ExitAction());

      setLayout(new BorderLayout());
      int gap = 3;
      setBorder(BorderFactory.createEmptyBorder(gap, gap, gap, gap));
      add(statusLabel, BorderLayout.NORTH);
      add(new JScrollPane(messageArea), BorderLayout.CENTER);
      add(createSouthPanel(), BorderLayout.SOUTH);

      setGameState(GameState.RESET);
      setGameState(GameState.FIRST_ROLL);
   }

   private JPanel createSouthPanel() {
      int gap = 20;
      JPanel diePanel = new JPanel(new GridLayout(1, 0, gap, gap));
      for (int i = 0; i < dieArray.length; i++) {
         dieArray[i] = new Die();
         diePanel.add(dieArray[i].getDieLabel());
      }

      JPanel buttonPanel = new JPanel(new GridLayout(1, 0, 10, 10));
      buttonPanel.add(rollButton);
      buttonPanel.add(exitButton);
      JPanel southPanel = new JPanel(new BorderLayout());
      southPanel.add(diePanel, BorderLayout.CENTER);
      southPanel.add(buttonPanel, BorderLayout.SOUTH);
      return southPanel;
   }

   public GameState getGameState() {
      return gameState;
   }

   public void rollAll() {
      for (Die die : dieArray) {
         die.roll();
         die.setSelectable(true);
      }
   }

   public void rollSelected() {
      for (Die die : dieArray) {
         if (die.isSelected()) {
            die.roll();
         }
         die.setSelected(false);
         die.setSelectable(false);
      }
   }

   public void setGameState(GameState gameState) {
      GameState currentState = this.gameState;
      this.gameState = gameState;
      rollButton.setAction(rollActionMap.get(gameState));

      if (currentState == GameState.RESET) {
         reset();
      } else if (currentState == GameState.FIRST_ROLL) {
         firstRoll();
      } else if (currentState == GameState.SECOND_ROLL) {
         secondRoll();
      }
   }

   private void firstRoll() {
      rollAll();
      statusLabel.setText(FIRST_ROLL_STATUS_TEXT);
   }

   private void secondRoll() {
      rollSelected();

      // TODO: calculate score and display

      statusLabel.setText(SECOND_ROLL_STATUS_TEXT);
   }

   public void reset() {
      for (Die die : dieArray) {
         die.reset();
      }
      statusLabel.setText(RESET_STATUS_TEXT);
   }
}

@SuppressWarnings("serial")
class RollAction extends AbstractAction {
   private DicePanel dicePanel;

   public RollAction(DicePanel dicePanel, GameState gameState) {
      super(gameState.getText());
      this.dicePanel = dicePanel;
      putValue(MNEMONIC_KEY, gameState.getMnemonic());
   }

   @Override
   public void actionPerformed(ActionEvent e) {
      dicePanel.setGameState(dicePanel.getGameState().next());
   }
}

@SuppressWarnings("serial")
class ExitAction extends AbstractAction {
   private static final String EXIT = "Exit";

   public ExitAction() {
      super(EXIT);
      putValue(MNEMONIC_KEY, KeyEvent.VK_X);
   }

   @Override
   public void actionPerformed(ActionEvent e) {
      Window win = SwingUtilities.getWindowAncestor(((Component)e.getSource()));
      win.dispose();
   }
}

enum GameState {
   FIRST_ROLL("First Roll", KeyEvent.VK_F), SECOND_ROLL("Second Roll", KeyEvent.VK_S), 
   RESET("Reset", KeyEvent.VK_R);

   private String text;
   private int mnemonic;

   private GameState(String text, int mnemonic) {
      this.text = text;
      this.mnemonic = mnemonic;
   }

   public int getMnemonic() {
      return mnemonic;
   }

   public String getText() {
      return text;
   }

   public GameState next() {
      int ordinal = ordinal();
      ordinal++;
      ordinal %= values().length;
      return values()[ordinal];
   }
}

class Die {
   private static final int BORDER_GAP = 3;
   private static final Border SELECTED_BORDER = 
         BorderFactory.createLineBorder(Color.red, BORDER_GAP);
   private static final Border UNSELECTED_BORDER = 
         BorderFactory.createEmptyBorder(BORDER_GAP, BORDER_GAP, BORDER_GAP, BORDER_GAP);

   private JLabel dieLabel = new JLabel();
   private Random random = new Random();
   private DieValue dieValue = DieValue.BLANK;
   private boolean selectable = false;
   private boolean selected = false;

   public Die() {
      reset();
      dieLabel.addMouseListener(new MouseAdapter() {
         @Override
         public void mousePressed(MouseEvent evt) {
            if (selectable) {
               setSelected(!selected);
            }
         }
      });
   }

   public Component getDieLabel() {
      return dieLabel;
   }

   public void setSelected(boolean selected) {
      this.selected = selected;
      Border border = selected ? SELECTED_BORDER : UNSELECTED_BORDER;
      dieLabel.setBorder(border);
   }

   public void roll() {
      int value = random.nextInt(6) + 1;
      dieValue = DieValue.getDieValue(value);
      dieLabel.setIcon(dieValue.getIcon());
   }

   public void reset() {
      dieValue = DieValue.BLANK;
      setSelected(false);
      setSelectable(false);
      dieLabel.setIcon(dieValue.getIcon());
   }

   public DieValue getValue() {
      return dieValue;
   }

   public boolean isSelected() {
      return selected;
   }

   public boolean isSelectable() {
      return selectable;
   }

   public void setSelectable(boolean selectable) {
      this.selectable = selectable;
   }
}

enum DieValue {
   BLANK(0, ""), 
   ONE(1, "One"), TWO(2, "Two"), THREE(3, "Three"), 
   FOUR(4, "Four"), FIVE(5, "Five"), SIX(6, "Six");

   private static final int OUT_FRAME = 110;
   private static final int ARC = 16;
   private static final float STROKE_WIDTH = 4f;
   private static final int SML_GAP = 2;
   private static final int OVAL_RADIUS = 24;
   private Icon icon;
   private String name;
   private int value;

   private DieValue(int value, String name) {
      this.value = value;
      this.name = name;
      this.icon = createIcon(value);
   }

   private Icon createIcon(int value) {
      BufferedImage img = new BufferedImage(OUT_FRAME, OUT_FRAME, 
            BufferedImage.TYPE_INT_ARGB);
      Graphics2D g2 = img.createGraphics();
      Stroke stroke = new BasicStroke(STROKE_WIDTH);
      g2.setColor(Color.white);
      g2.fillRoundRect(0, 0, OUT_FRAME, OUT_FRAME, ARC, ARC);
      g2.setColor(Color.black);
      g2.setStroke(stroke);
      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
      g2.drawRoundRect(SML_GAP, SML_GAP, OUT_FRAME - SML_GAP * 2, 
            OUT_FRAME - SML_GAP * 2, ARC, ARC);


      g2.setColor(Color.black);
      switch (value) {
      case 1:
         fillOval(g2, 1, 1);
         break;
      case 2:
         fillOval(g2, 0, 0);
         fillOval(g2, 2, 2);
         break;
      case 3:
         fillOval(g2, 0, 0);
         fillOval(g2, 1, 1);
         fillOval(g2, 2, 2);
         break;
      case 4:
         fillOval(g2, 0, 0);
         fillOval(g2, 0, 2);
         fillOval(g2, 2, 0);
         fillOval(g2, 2, 2);
         break;
      case 5:
         fillOval(g2, 0, 0);
         fillOval(g2, 0, 2);
         fillOval(g2, 1, 1);
         fillOval(g2, 2, 0);
         fillOval(g2, 2, 2);
         break;
      case 6:
         fillOval(g2, 0, 0);
         fillOval(g2, 0, 1);
         fillOval(g2, 0, 2);
         fillOval(g2, 2, 0);
         fillOval(g2, 2, 1);
         fillOval(g2, 2, 2);
         break;

      default:
         break;
      }

      g2.dispose();
      return new ImageIcon(img);
   }

   private void fillOval(Graphics2D g2, int row, int col) {
      double rectWidth = OUT_FRAME - 4 * STROKE_WIDTH;
      int x = (int) (2 * STROKE_WIDTH - OVAL_RADIUS / 2 + (col + 0.5) * rectWidth / 3);
      int y = (int) (2 * STROKE_WIDTH - OVAL_RADIUS / 2 + (row + 0.5) * rectWidth / 3);

      g2.fillOval(x, y, OVAL_RADIUS, OVAL_RADIUS);
   }

   public static DieValue getDieValue(int value) {
      for (DieValue dieImage : DieValue.values()) {
         if (dieImage.getValue() == value) {
            return dieImage;
         }
      }
      return null;
   }

   public Icon getIcon() {
      return icon;
   }

   public String getName() {
      return name;
   }

   public int getValue() {
      return value;
   }

}

显示为:

第一卷: First Roll

第二卷: Second Roll

复位: Reset