JOptionPane.showInputDialog()被调用两次,为什么?

时间:2015-12-19 14:13:54

标签: java

在我调用的类[TinyDebug]中的showDebugWindow()方法中,即使输入正确的密码后,JOptionPane.showInputDialog()也会被调用两次,为什么会这样?

此外,此代码正在我的Game类中的update()方法执行,该方法每秒调用一次。

请看下面的问题代码集。

游戏:

public class Game extends TinyPixel {
    private static Game game;

    private static KeyManager keyManager;
    private static MouseManager mouseManager;
    private static GameStateManager sManager;

    private boolean isRunning;
    private int targetTime;
    private final int frameCap = 60;

    public Game(String gameTitle, String gameVersion, int gameWidth, int gameRatio, int gameScale) {
        super(gameTitle, gameVersion, gameWidth, gameRatio, gameScale);
        init();
    }

    public void init() {
        Utilities.printMessage("\t\t-[" + Library.gameTitle + "]-" +
                "\n[Game Version]: " + gameVersion +
                "\n[Unique Build Number]: " + Utilities.generateCode(16));

        ResourceLoader.loadImages();
        ResourceLoader.loadMusic();
        ResourceLoader.loadSound();
        ResourceLoader.loadFonts();

        keyManager = new KeyManager(this);
        mouseManager = new MouseManager(this);
        sManager = new GameStateManager(this);
    }

    @Override public void update() {
        sManager.update();
        mouseManager.update();
    }

    @Override public void render() {
        BufferStrategy bs = tinyWindow.getCanvas().getBufferStrategy();
        if (bs == null) {
            tinyWindow.getCanvas().createBufferStrategy(3);
            tinyWindow.getCanvas().requestFocus();
            return;
        }

        Graphics g = bs.getDrawGraphics();
        g.clearRect(0, 0, gameWidth, gameHeight);
        sManager.render(g);
        g.dispose();
        bs.show();
    }

    public void start() {
        if(isRunning) return;
        isRunning = true;
        new Thread(this, gameTitle + " " + gameVersion).start();
    }

    public void stop() {
        if(!isRunning) return;
        isRunning = false;
    }

    @Override public void run() {
        isRunning = true;

        targetTime = 1000 / frameCap;

        long start = 0;
        long elapsed = 0;
        long wait = 0;

        while (isRunning) {
            start = System.nanoTime();
            update();
            render();
            elapsed = System.nanoTime() - start;
            wait = targetTime - elapsed / 1000000;
            if (wait < 0) wait = 5;
            try {
                Thread.sleep(wait);
            } catch (InterruptedException e) {
                Utilities.printErrorMessage("Failed to Load " + gameTitle + " " + gameVersion);
            }
        }

        stop();
    }

    public static KeyManager getKeyManager() {
        return keyManager;
    }

    public static GameStateManager getsManager() {
        return sManager;
    }

    public static Game getGame() {
        return game;
    }
}

GameLauncher:

public class GameLauncher {
    public static void main(String[] args) {
        new Game(Library.gameTitle, Library.gameVersion, 640, TinyPixel.Square, 1).start();
    }
}

GameStateManager:

public class GameStateManager {
    private int numStates = 3;

    public static final int MenuState = 0;
    public static final int LoadingState = 1;
    public static final int GameState = 2;

    public static GameState[] gStates;
    private static int currentState;
    private static String currentMusic;

    protected Game game;

    public GameStateManager(Game game) {
        this.game = game;
        init();
    }

    private void init() {
        gStates = new GameState[numStates];

        currentState = MenuState;
        //currentMusic = Library.backgroundMusic;
        //TinyPlayer.playMusic(currentMusic);
        loadState(currentState);
    }

    private void loadState(int gState) {
        if (gState == MenuState) gStates[gState] = new MenuState(game, this);
        if (gState == LoadingState) gStates[gState] = new LoadingState(game, this);
        if (gState == GameState) gStates[gState] = new PlayState(game, this);       
    }

    private void unloadState(int gState) {
        gStates[gState] = null;
    }

    public void setState(int gState) {
        unloadState(gState);
        currentState = gState;
        loadState(gState);
    }

    private void changeMusic(String key) {
        if (currentMusic.equals(key)) return;
        TinyPlayer.stopMusic(currentMusic);
        currentMusic = key;
        TinyPlayer.loop(currentMusic);
    }

    public void update() {
        try {
            gStates[currentState].update();
        } catch (Exception e) {}
    }

    public void render(Graphics g) {
        try {
            gStates[currentState].render(g);
        } catch (Exception e) {}
    }

    public static int getCurrentState() {
        return currentState;
    }
}

游戏状态:

public abstract class GameState {
    protected Game game;
    protected GameStateManager sManager;

    public GameState(Game game, GameStateManager sManager) {
        this.game = game;
        this.sManager = sManager;
        init();
    }

    public abstract void init();
    public abstract void update();
    public abstract void render(Graphics g);
}

MenuState:

public class MenuState extends GameState {
    private Rectangle playBtn, exitBtn;
    private TinyDebug tinyDebug;
    public static final Color DEFAULT_COLOR = new Color(143, 48, 223);

    public MenuState(Game game, GameStateManager sManager) {
        super(game, sManager);
        init();
    }

    public void init() {
        tinyDebug = new TinyDebug();

        int xOffset = 90, yOffset = 70;
        playBtn = new Rectangle(Game.getWidth() / 2 - xOffset, Game.getHeight() / 2, 180, 40);
        exitBtn = new Rectangle(Game.getWidth() / 2 - xOffset, Game.getHeight() / 2 + yOffset, 180, 40);
    }

    public void update() {
        if (Game.getKeyManager().debug.isPressed()) { 
            Game.getKeyManager().toggleKey(KeyEvent.VK_Q, true);
            tinyDebug.showDebugWindow();
        }

        if (Game.getKeyManager().space.isPressed()) { 
            Game.getKeyManager().toggleKey(KeyEvent.VK_SPACE, true);
            sManager.setState(GameStateManager.LoadingState);
        }

        if (Game.getKeyManager().exit.isPressed()) { 
            Game.getKeyManager().toggleKey(KeyEvent.VK_ESCAPE, true);
            System.exit(0);
        }
    }

    public void render(Graphics g) {
        //Render the Background
        g.drawImage(Library.menuBackground, 0, 0, Game.getWidth(), Game.getHeight(), null);

        //Render the Game Version
        TinyFont.drawFont(g, new Font(Library.gameFont, Font.PLAIN, 8), Color.white, "Version: " + Library.gameVersion, Game.getWidth() / 2 + 245, Game.getHeight() - 30);

        //Render the Social Section
        TinyFont.drawFont(g, new Font(Library.gameFont, Font.PLAIN, 8), Color.white, "@nickadamou", 20, Game.getHeight() - 60);
        TinyFont.drawFont(g, new Font(Library.gameFont, Font.PLAIN, 8), Color.white, "@nicholasadamou", 20, Game.getHeight() - 45);
        TinyFont.drawFont(g, new Font(Library.gameFont, Font.PLAIN, 8), Color.white, "Ever Tried? Ever Failed? No Matter. Try Again. Fail Again. Fail Better.", 20, Game.getHeight() - 30);

        //Render the Debug Section
        tinyDebug.renderDebug(g);

        g.setColor(Color.white);
        g.drawRect(playBtn.x, playBtn.y, playBtn.width, playBtn.height);
        g.drawRect(exitBtn.x, exitBtn.y, exitBtn.width, exitBtn.height);

        TinyFont.drawFont(g, new Font(Library.gameFont, Font.PLAIN, 14), Color.white, "Play Game [space]", playBtn.x + 10, playBtn.y + 25);
        TinyFont.drawFont(g, new Font(Library.gameFont, Font.PLAIN, 14), Color.white, "Exit Game [esc]", exitBtn.x + 20, exitBtn.y + 25);
    }
}

的KeyManager:

public class KeyManager implements KeyListener {
private Game game; 

   public KeyManager(Game game) {
    this.game = game;
    game.getTinyWindow().getCanvas().addKeyListener(this);
   }

        public class Key {
            private int amtPressed = 0;
            private boolean isPressed = false;

            public int getAmtPressed() {
                return amtPressed;
            }

            public boolean isPressed() {
                return isPressed;
            }

            public void toggle(boolean isPressed) {
                this.isPressed = isPressed;
                if (isPressed) amtPressed++;
            }
        }

        public Key up = new Key();
        public Key down = new Key();
        public Key left = new Key();
        public Key right = new Key();
        public Key space = new Key();
        public Key debug = new Key();
        public Key exit = new Key();

        public void keyPressed(KeyEvent key) {
            toggleKey(key.getKeyCode(), true);
        }

        public void keyReleased(KeyEvent key) {
            toggleKey(key.getKeyCode(), false);
        }

        public void keyTyped(KeyEvent e) {}

        public void toggleKey(int keyCode, boolean isPressed) {
            game.getTinyWindow().getFrame().requestFocus();
            game.getTinyWindow().getCanvas().requestFocus();

            if (keyCode == KeyEvent.VK_W || keyCode == KeyEvent.VK_UP) {
                up.toggle(isPressed);
            }
            if (keyCode == KeyEvent.VK_S || keyCode == KeyEvent.VK_DOWN) {
                down.toggle(isPressed);
            }
            if (keyCode == KeyEvent.VK_A || keyCode == KeyEvent.VK_LEFT) {
                left.toggle(isPressed);
            }
            if (keyCode == KeyEvent.VK_D || keyCode == KeyEvent.VK_RIGHT) {
                right.toggle(isPressed);
            }

            if (keyCode == KeyEvent.VK_SPACE) {
                space.toggle(isPressed);
            }

            if (keyCode == KeyEvent.VK_Q) {
                debug.toggle(isPressed);
            }

            if (keyCode == KeyEvent.VK_ESCAPE) {
                exit.toggle(isPressed);
            }
        }

        @SuppressWarnings("unused")
        private void debug(KeyEvent key) { 
            System.out.println("[keyCode]: " + key.getKeyCode());
        }
}

TinyDebug:

public class TinyDebug {
    private final String appTitle = Library.gameTitle;
    private String tinyPassword, tinyBuildCode;

    private boolean isAllowedDebugging = false;
    private boolean isShowingTinyText = false;

    public TinyDebug() {
        tinyPassword = "test123";                     // - Standard Password (Non-Renewable)
        //tinyPassword = Utilities.generateCode(16);   // - Stronger Password (Renewable)
        writePasswordToFile(tinyPassword); 

        tinyBuildCode = Utilities.generateCode(16);
    }


    //TODO: This method invokes JOptionPane.showInputDialog() twice even after I input the correct password, why?
    public void showDebugWindow() {
        boolean hasRun = true; 

        if (hasRun) { 
            Clipboard cBoard = Toolkit.getDefaultToolkit().getSystemClipboard();
            cBoard.setContents(new StringSelection(tinyPassword), null);

            if (isAllowedDebugging() && isShowingTinyText()) return;

            String userPassword = JOptionPane.showInputDialog("Input Password to Enter [TinyDebug].");

            do {
                if (userPassword.equals(tinyPassword)) {
                    JOptionPane.showMessageDialog(null, "[" + appTitle + "]: The Password Entered is Correct.", appTitle + " Message", JOptionPane.PLAIN_MESSAGE);
                    isAllowedDebugging(true);
                    isShowingTinyText(true);
                    break;
                } else { 
                    JOptionPane.showMessageDialog(null, "[Error Code]: " + Utilities.generateCode(16) + "\n[Error]: Password is Incorrect.", appTitle + " Error Message", JOptionPane.ERROR_MESSAGE);
                    System.exit(0);
                }
            } while (userPassword != null || userPassword.trim().isEmpty() != true);
        }

        hasRun = false;
    }

    @SuppressWarnings("unused")
    public void renderDebug(Graphics g) {
        if (isAllowedDebugging()) {
            //TODO: Render Debug Information.
            TinyFont.drawFont(g, new Font(Library.gameFont, Font.PLAIN, 8), Color.white, "Tiny Pixel [Debug]", 5, 10);
            TinyFont.drawFont(g, new Font(Library.gameFont, Font.PLAIN, 8), Color.white, "#. [Options are Shown Here]", 10, 25);

            if (isShowingTinyText()) {
                String debugHeader =  appTitle + " Information";
                String debugPasswordField = appTitle + " Information:";
                String debugBuildNumber = appTitle + " Unique Build #: " + getTinyBuildCode();
            }
        }
    }

    //TODO: This method prints the [Utilities.printMessage(appTitle + ": [tinyPassword] Generated and Stored @ FilePath: \n" + logFile.getAbsolutePath());] twice, why?
    private void writePasswordToFile(String tinyPassword) {
        BufferedWriter bWriter = null;
        try {
            File logFile = new File("tinyPassword.txt");

            Utilities.printMessage(appTitle + ": [tinyPassword] Generated and Stored @ FilePath: \n" + logFile.getAbsolutePath());

            bWriter = new BufferedWriter(new FileWriter(logFile));
            bWriter.write(appTitle + " debug Password: " + tinyPassword);
        } catch (Exception e) {
            Utilities.printErrorMessage("Failed to Write [tinyPassword] to File.");
        } finally {
            try {
                bWriter.close();
            } catch (Exception e) {
                Utilities.printErrorMessage("Failed to Close [bWriter] Object.");
            }
        }
    }

    public String getTinyPassword() {
        return tinyPassword;
    }

    public String getTinyBuildCode() {
        return tinyBuildCode;
    }

    public void isShowingTinyText(boolean isShowingTinyText) {
        this.isShowingTinyText = isShowingTinyText;
    }

    public boolean isShowingTinyText() {
        return isShowingTinyText;
    }

    public void isAllowedDebugging(boolean isAllowedDebugging) {
        this.isAllowedDebugging = isAllowedDebugging;

        if (isAllowedDebugging) showDebugWindow();
    }

    public boolean isAllowedDebugging() {
        return isAllowedDebugging;
    }
}

1 个答案:

答案 0 :(得分:1)

在showDebugWindow()方法中,您有以下声明:

if (userPassword.equals(tinyPassword)) {
                ...
                isAllowedDebugging(true); // Problematic statement
                ...
            }

调用此方法:

public void isAllowedDebugging(boolean isAllowedDebugging) {
    this.isAllowedDebugging = isAllowedDebugging;

    if (isAllowedDebugging) showDebugWindow(); // Second call?
}

如您所见,当您设置isAllowedDebugging开关时,您也调用该方法,因此当您输入密码正确时,会发生第二次调用。