简体   繁体   English

Java swing 带有自定义按钮的错误

[英]Java swing bug with custom button

Having problems creating a custom JButton that is an Image.创建作为图像的自定义 JButton 时遇到问题。 I had everything working with a normal JButton (like in the comment on the 2nd line) this way I wouldn't have to get an InputStream and start the button has an icon.我可以使用普通的 JButton 进行所有操作(例如在第二行的评论中),这样我就不必获取 InputStream 并启动按钮有一个图标。 The trouble I'm having is that when I pressed the replay button (to play again) the window closes and only one window should pop out (as it happens with a "normal" JButton) but in this case 4-5 windows reopen and I don't know why.我遇到的麻烦是,当我按下重播按钮(再次播放)时,window 关闭,只有一个 window 应该弹出(因为它发生在“正常”JButton 上)但在这种情况下,4-5 Z0F4137ED1502B5045DZ0 和3AA52B5045D6B 重新打开我不知道为什么。

I started thinking it was because the time to get an InputStream and doing ImageIO.read() the game would start and see that the variable running was false and then started reopening windows until it's true but I can't see how to verify that.我开始认为这是因为获取InputStream并执行ImageIO.read()的时间,游戏将开始并看到变量 running 为假,然后开始重新打开 windows 直到它为真,但我看不出如何验证。

Note: I have functions that on ActionPerformed verify if the snake has collided and if so running = false and GameOver() will be called注意:我有在 ActionPerformed 上验证蛇是否碰撞的函数,如果是这样, running = falseGameOver()将被调用

public class GamePanel extends JPanel implements ActionListener { 
    JButton replay; //= new JButton("Play Again"); 
    GamePanel() {
        ...
        try {
            InputStream is_replay = this.getClass().getResourceAsStream("/Snake/lib/img/playagain.png");
            ImageIcon icon = new ImageIcon(ImageIO.read(is_replay));
            replay = new JButton(icon);
            replay.setBorder(BorderFactory.createEmptyBorder());
            replay.setContentAreaFilled(false);
            ...
        } catch (IOException|FontFormatException e) {
            e.printStackTrace();
        }

        this.add(replay);
        replay.setVisible(false);
        replay.setBounds(SCREEN_WIDTH/2 - 100, SCREEN_HEIGHT - 200, 200, 100);
        ...
        startGame();
    }

    public void startGame() {
        spawnApple();
        running = true;
        timer = new Timer(DELAY, this);
        timer.start();
    }

    public void gameOver(Graphics g) {
        ...

        replay.setVisible(true);
        replay.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if(e.getSource() == replay) {
                    JComponent comp = (JComponent)e.getSource();
                    Window win = SwingUtilities.getWindowAncestor(comp);
                    win.dispose();  //It will close the current window
                    new GameFrame();  //It will create a new game
                }
            }
        });
    }
}

public class GameFrame extends JFrame {
    GameFrame() {
        JPanel panel = new GamePanel();
        this.add(panel);
        panel.setLayout(null);  //Needed to add components
        this.setTitle("Snake Game");
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setResizable(false);
        this.pack();  //Fit JFrame to the components
        this.setVisible(true);
        this.setLocationRelativeTo(null);
    }
}

public class SnakeGame {
    public static void main(String[] args) throws Exception {
        new GameFrame();
    }
}

"in this case 4-5 windows reopen" “在这种情况下 4-5 windows 重新打开”

This suggests that you are probably adding multiple ActionListeners to the replay JButton.这表明您可能正在向重放 JButton 添加多个 ActionListener。 A new listener is added each time game over method is called, and this is incorrect.每次调用 game over 方法时都会添加一个新的侦听器,这是不正确的。 I would not add the ActionListener to the button in the game over method but rather add it once where you create the replay button.我不会将 ActionListener 添加到游戏结束方法中的按钮,而是在创建重播按钮的地方添加一次

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM