0

JButtons only show up when I hover over them. Also disappear when I resize window. The error lies in the constructor here. I am extending a JFrame. Removing the JPanel doesn't fix it. Please help.

public GameBoard(String title, int width, int height)
{
    super();
    this.boardWidth = width;
    this.boardHeight = height;

    // Create game state
    this.board = new GameSquare[width][height];

    // Set up window
    setTitle(title);
    setSize(720,720);
    setContentPane(boardPanel);
    setLocationRelativeTo(null);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    boardPanel.setLayout(new GridLayout(height,width));

    int decorator = 0;
    for (int y = 0; y<height; y++){
        decorator++;
        for (int x = 0; x<width; x++){
            if (decorator % 2 == 0)
                board[x][y] = new GameSquare(x, y, "BLACK");
            else
                board[x][y] = new GameSquare(x, y, "WHITE");

            board[x][y].addActionListener(this);
            boardPanel.add(board[x][y]);
            decorator++;
        }
    }
    // make our window visible
    setVisible(true);
}

MCV Example.

package chess;

public class GameBoard extends JFrame implements ActionListener
{
private JPanel boardPanel = new JPanel();

private int boardHeight;
private int boardWidth;
private GameSquare[][] board; 

public static void main(String[] args) {

    SwingUtilities.invokeLater(new Runnable() {

  @Override
  public void run() {
    GameBoard gameBoard = new GameBoard("The Revolutionary War",8,8);
  }
    });
}


/**
 * Create a new game board of the given size.
 * As soon as an instance of this class is created, it is visualised
 * on the screen.
 * 
 * @param title the name printed in the window bar.
 * @param width the width of the game area, in squares.
 * @param height the height of the game area, in squares.
 */
public GameBoard(String title, int width, int height)
{
    super();
    this.boardWidth = width;
    this.boardHeight = height;

    // Create game state
    this.board = new GameSquare[width][height];

    // Set up window
    setTitle(title);
    setSize(720,720);
    setContentPane(boardPanel);
    setLocationRelativeTo(null);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    boardPanel.setLayout(new GridLayout(height,width));

    for (int y = 0; y<height; y++){
        for (int x = 0; x<width; x++){

            board[x][y] = new GameSquare(x, y, this);
            board[x][y].setEnabled(true);
            board[x][y].addActionListener(this);

            boardPanel.add(board[x][y]);
        }
    }
    // make our window visible
    setVisible(true);
}

/**
 * Returns the GameSquare instance at a given location. 
 * @param x the x co-ordinate of the square requested.
 * @param y the y co-ordinate of the square requested.
 * @return the GameSquare instance at a given location 
 * if the x and y co-ordinates are valid - null otherwise. 
 */
public GameSquare getSquareAt(int x, int y)
{
    if (x < 0 || x >= boardWidth || y < 0 || y >= boardHeight)
        return null;

    return (GameSquare) board[x][y];
}

public void actionPerformed(ActionEvent e)
{
    // The button that has been pressed.s
    GameSquare square = (GameSquare)e.getSource();

}

//BufferedImage background = ImageIO.read(new File("/path/to/image.jpg"));
}

The other class is here:

package chess;

public class GameSquare extends JButton {

/**
 * 
 */
private static final long serialVersionUID = 1L;
private int x;
private int y;
private ChessPiece chessPiece;
private boolean selected;
private ImageIcon icon;

GameSquare(int xPos, int yPos, GameBoard board){
    super();
    x = xPos;
    y = yPos;
    chessPiece = null; 
    selected = false;

    // Test to see colour of the base tile
    if ((xPos+yPos) % 2 == 1){
        icon = new ImageIcon(getClass().getResource("/pics/black.png"));
        this.setIcon(icon);
    }
    else if ((xPos+yPos) % 2 == 0) {
        icon = new ImageIcon(getClass().getResource("/pics/white.png"));
        this.setIcon(icon);
    }
}

public int getX(){
    return x;
}

public int getY(){
    return y;
}

public void setChessPiece(ChessPiece piece){
    chessPiece = piece;
}

public ChessPiece getChessPiece(){
    return chessPiece;
}

public void setImage(){
    setIcon(chessPiece.getIcon());
}

public void select(){
    selected = true;
    setIcon(new ImageIcon(getClass().getResource("pics/selected.png")));
}

public void deselect(){
    selected = false;
    if (chessPiece == null) setIcon(icon);
    else setImage();
}

}
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • 1
    `"The error lies in the constructor here."` -- are you 100% sure about this? If you knew the cause of the problem, my guess is that you'd likely have a fix. Please post a valid [mcve] for the best chance of our understanding your problem and getting a solution. – Hovercraft Full Of Eels Jul 14 '17 at 16:42
  • 1) Please don't enter an answer, when you really need to [edit] the question. 2) But before you do, note that code is not an MCVE as suggested by @HovercraftFullOfEels. It lacks imports and (most importantly) the `ChessPiece` class. Also, ideally an MCVE should only have **one** class declared **`public`** so they can be put in the same code block when posting, copy/pasting and file when compiling. 3) One way to get image(s) for an example is to hot link to images seen in [this Q&A](http://stackoverflow.com/q/19209650/418556). – Andrew Thompson Jul 14 '17 at 17:18
  • Quit posting the same question multiple times: https://stackoverflow.com/questions/45105887/jbuttons-only-show-on-mouse-hover-chess-game. We can't keep track of all the suggestions that have been made. – camickr Jul 14 '17 at 18:28
  • Please see edits to answer – Hovercraft Full Of Eels Jul 14 '17 at 19:10
  • ?? Again, please see edit to answer – Hovercraft Full Of Eels Jul 15 '17 at 14:01

2 Answers2

2

Your problem is due to your overriding JPanel's getX() and getY(). These methods are used by the container's layout managers to help place components, and by overriding these key methods, you mess up the ability of the layouts to do this. Please change the names of those methods to something that does not override a key method of the class. If this is a chess square, I'd rename the variables to rank and file, and have getRank() and getFile() methods.

public class GameSquare extends JButton {
    private int file;
    private int rank;
    // ....

    GameSquare(int xPos, int yPos, GameBoard board){
        super();
        file = xPos;
        rank = yPos;
        chessPiece = null; 
        selected = false;

        // .....
    }

    public int getFile(){
        return file;
    }

    public int getRank(){
        return rank;
    }

    // .....
}
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
0

add

pack();

in the GameBoard class, before setting visible. This will ensure that the size is correct and make room for any buttons which are hanging off the edge... This will make the frame the size of the JPanel, exactly as it is rendered after all objects are added.

also maybe

setResizable(false);

as it will stop you resizing your windows, and with images this can cause buttons to disappear as well as reappear if the user accidentally clicks the sides. I'd put this underneath: setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

Tim Weeks
  • 9
  • 1