-1

i'm trying a simple graphics game. what i want is when player loses, a "game over" message to be displayed and a JButton to be added to the panel. Here is the code:

@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);

    drawBoard(g);
}

private void drawBoard(Graphics g) {

    if(inGame) {
        // painting code goes here
    }

    else {
        gameOver(g);
    }

}

private void gameOver(Graphics g) {

    Font font = new Font("Monospaced", Font.BOLD, 18);
    FontMetrics metrics = g.getFontMetrics(font);

    g.setColor(Color.WHITE);
    g.setFont(font);

    String msg = "Game Over";
    g.drawString(msg, (B_WIDTH - metrics.stringWidth(msg)) / 2, B_HEIGHT / 2);

    JButton btn = new JButton("Again");
    add(btn);
    btn.setLocation(B_WIDTH/2, B_HEIGHT/2); // not working
    revalidate() // drives execution in a recursive loop

}

The problem is that if i put revalidate() infinite buttons are added. If i dont, no button added. Could someone please explain?

Thanks!

EDIT: I followed MrPk's solution and changed gameOver() as this:

    private void gameOver(Graphics g) {

    Font font = new Font("Monospaced", Font.BOLD, 18);
    FontMetrics metrics = g.getFontMetrics(font);

    g.setColor(Color.WHITE);
    g.setFont(font);

    String msg = "Game Over";
    g.drawString(msg, (B_WIDTH - metrics.stringWidth(msg)) / 2, B_HEIGHT / 2);

   if ( !Arrays.asList(getComponents()).contains(btn) ) {
      add(btn);
      btn.setLocation(100,100);       
   }

   if (Arrays.asList(getComponents()).contains(btn) ) {
       System.out.println("added");
       System.out.println(btn.getX() + "  " + btn.getY());
   }    
}

When the game ends, the button is still invisible but the program prints :

added
100 100

So, -if i understood right- the problem is that the button is added, but not showing, right? I'd like to know why this happens, and not how to fix this.

thanks again

antonis
  • 96
  • 1
  • 8
  • 2
    When the components is being painted, `paintComponent` will call `drawBoard`, and `drawBoard` calls `gameOver`, and `gameOver` adds a button, and then calls `revalidate`, which will trigger another paint. That will continue looping and adding new buttons. Don't add buttons and revalidate inside a `paint` call. – khelwood Feb 17 '17 at 09:17
  • @khelwood thank you, that's what i suspected too. But where should i place the code for adding the button? I want it to be added when `gameOver()` gets called. – antonis Feb 17 '17 at 09:24
  • 1
    Presumably at some point in the logic of your game, something happens that means the game over. At that point, you could call `gameOver`. But don't call it from anything called by a paint method. – khelwood Feb 17 '17 at 09:30
  • 1) For better help sooner, post a [MCVE] or [Short, Self Contained, Correct Example](http://www.sscce.org/). 2) *"..and a JButton to be added to the panel.."* Use a [`CardLayout`](http://download.oracle.com/javase/8/docs/api/java/awt/CardLayout.html) as shown in [this answer](http://stackoverflow.com/a/5786005/418556). – Andrew Thompson Feb 17 '17 at 09:37
  • `what i want is when player loses, a "game over" message to be displayed and a JButton to be added to the panel` - typically you would display a JOptionPane with a message. Read the section from the Swing tutorial on [How to Make Dialogs](http://docs.oracle.com/javase/tutorial/uiswing/components/dialog.html). – camickr Feb 17 '17 at 15:48

1 Answers1

0

Use repaint() instead of revalidate().

Here is the difference between repaint() and revalidate():

Java Swing revalidate() vs repaint()

Community
  • 1
  • 1
jobs
  • 63
  • 1
  • 11
  • Funny that in the answers of the link, they are saying to call both and not just one ;) – AxelH Feb 17 '17 at 09:18
  • @AxelH Depends on what you're doing. In this case I think repaint() is enough. – jobs Feb 17 '17 at 09:19
  • @ Colin Herzog I have already tried `repaint()`, both alone and after `revalidate()`, but i 'm getting the same results: nothing happens with `repaint()`, and infinite buttons with both `repaint()` and `revalidate()` – antonis Feb 17 '17 at 09:27