1

I have created a "Game Over!" page when the user loses in my game. Under g.drawString(...), I am trying to create a button that the user can click to restart the game. I am having trouble getting a button to appear and stay visible.

How can I create a JButton in a custom paint(Graphics g) method in Java? Any suggestions?

import java.awt.event.*;
import javax.swing.*;
import java.awt.*;

public class Game extends JPanel implements KeyListener {

    private Player player;
    private Stage stage;
    private Stage stageLeft;
    private Stage stageRight;
    private EnemyManager manager;

    private boolean isGameOver = false;
    private boolean restart = false;

    public Game() {
        setSize(800,600);
        setPreferredSize(new Dimension(800,600));
        setFocusable(true);
        setBackground(Color.WHITE);
        requestFocus();
        addKeyListener(this);

        stage = new Stage(0, 540, 800, 100);
        stageLeft = new Stage(-1, 0, 1, 600);
        stageRight = new Stage(800, 0, 1, 600);
        player = new Player(this, 400, 400);
        manager = new EnemyManager(this, 10);
    }

    @Override
    public void update(Graphics g) {
        paint(g);
    }

    public void paint(Graphics g) {
        g.setColor(Color.WHITE);
        g.fillRect(0,0,getWidth(),getHeight());

        stage.draw(g);
        stageLeft.draw(g);
        stageRight.draw(g);
        if(!isGameOver || restart) {
            player.draw(g);
            manager.draw(g);
        } else {
            g.setColor(Color.BLACK);
            g.fillRect(0, 0, getWidth(), getHeight());

            g.setColor(Color.WHITE);
            g.setFont(new Font("Century Gothic", Font.BOLD, 24));
            g.drawString("Game Over!", 330, 275);

            g.drawRect(330, 300, 145, 40);
            g.drawString("Restart", 350, 320);

            //TODO: Make a restart button that works
        }

        g.dispose();
        repaint();
    }

    @Override
    public void keyPressed(KeyEvent e) {
        int c = e.getKeyCode();
        if(c == KeyEvent.VK_W) {

        }
        if(c == KeyEvent.VK_A) {
            player.setxDir(-1);
        }
        if(c == KeyEvent.VK_S) {

        }
        if(c == KeyEvent.VK_D) {
            player.setxDir(1);
        }
    }

    public void setGameOver(boolean flag) {
        isGameOver = flag;
    }

    @Override
    public void keyReleased(KeyEvent e) {
        player.setxDir(0);
        player.setyDir(0);
    }

    @Override
    public void keyTyped(KeyEvent e) {

    }

    public Stage getStage() {
        return stage;
    }

    public Stage getStageLeft() { return stageLeft; }

    public Stage getStageRight() { return stageRight; }

    public EnemyManager getEnemyManager() {
        return manager;
    }

    public static void main(String[] args) {

        Game game = new Game();

        JFrame frame = new JFrame();
        frame.setTitle("Java Game");
        frame.add(game);
        frame.pack();
        frame.setPreferredSize(new Dimension(800,600));
        frame.setResizable(false);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // Center window
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}
Peter O.
  • 32,158
  • 14
  • 82
  • 96
TheAnonymous010
  • 725
  • 7
  • 19

1 Answers1

2

Regarding,

How can I create a JButton in a custom paint(Graphics g) method in java?

Answer: you don't. Never create or place components within any of the painting methods. These methods are for rendering images and rendering only and should never be used for component creation or program logic.

This question is an XY Problem:

I have created a "Game Over!" page when the user loses in my game. Under g.drawString(...), I am trying to create a button that the user can click to restart the game. I am having trouble getting a button to appear and stay visible.

In that you're asking for a solution to a specific code problem, when the true best solution is to use a different approach. I suggest:

  • Create a JPanel that displays your background image in its paintComponent method, not its paint method as per the Swing painting tutorials
  • Add your JButton to this JPanel as you would add it to any JPanel, and not in its painting methods.
  • You're better off creating a separate JPanel to do this, and then swap JPanels when needed via a CardLayout.

Other issues:

  • Never dispose of a Graphics object given to you by the JVM. Doing this breaks the painting chain.
  • You should almost always call the super's painting method inside of your override so that the painting chain can continue. So if you override paintComponent as per my recommendation, you should be sure to call the super.paintComponent(g) method within your own override.
  • Never call repaint() from within a painting method. This is a very bad way to try to do animation as it is uncontrollable and risky.
  • Don't override update() as while this is done for AWT painting, it is not generally used for Swing graphics or animation.
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • Thank you for your quick response. I will take all of this into consideration and see what I can make out of this game. I am quite new to Java development and this helps me out a bunch. – TheAnonymous010 Jun 14 '15 at 01:37
  • I have the CardLayout working and everything seems fine but my key input no longer works. Do you know of any fixes around this? I have been researching it, but nothing I find seems to do the trick. – TheAnonymous010 Jun 14 '15 at 03:22
  • 1
    @TheAnonymous010: yes, use Key Bindings, not a KeyListener. This should have been one of my recommendations, since Key Bindings are much more flexible and forgiving. – Hovercraft Full Of Eels Jun 14 '15 at 03:30
  • Hovercraft Full Of Eels gave some excellent advice. Take a look at my article, [Retro Snake Game](http://java-articles.info/articles/?p=768), to see how to layout a game with a Game Over image and where to place a restart button. – Gilbert Le Blanc Jun 14 '15 at 15:08