1

I'm creating a chess game where the main panel is using BorderLayout, there is a panel at NORTH for buttons, a panel at CENTER for the board itself (set to GridLayout) and a sidebar at East.

I have made the JFrame unresizable and I'd like the chessboard to fit the panels in so that the East panel is a lot wider (maybe 200 pixels) and the board remains a square. I can't figure out how to change the sizes of these components individually.

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

public class GameWindow extends JFrame {

    private final JPanel playArea = new JPanel(new BorderLayout(3,3));
    private final JButton[][] boardSquares = new JButton[8][8];
    private final JPanel board;
    private final JPanel sidebar = new JPanel();
    private final JLabel message = new JLabel("Game by ...");

    public  GameWindow() {
        playArea.setBorder(new EmptyBorder(5, 5, 5, 5));

        JToolBar tools = new JToolBar();


        tools.setFloatable(false);
        playArea.add(tools, BorderLayout.PAGE_START);
        tools.add(new JButton("New Game"));
        tools.add(new JButton("Save"));
        tools.add(new JButton("Restore")); 
        tools.addSeparator();
        tools.add(new JButton("Resign"))
        tools.addSeparator();
        tools.add(message);

        board = new JPanel(new GridLayout(0, 8));
        board.setBorder(new LineBorder(Color.BLACK));
        playArea.add(board, BorderLayout.CENTER);
        playArea.add(sidebar, BorderLayout.EAST);

        Insets buttonMargin = new Insets(0,0,0,0);
        for (int i = 0; i < boardSquares.length; i++) {
           for (int j = 0; j < boardSquares[i].length; j++) {
                JButton square = new JButton();
                square.setMargin(buttonMargin);
                if ((i+j)%2 == 0) {
                    square.setBackground(Color.WHITE);
                } 
                else {
                    square.setBackground(Color.BLACK);
                }
                board.setSize(600, 600);
                board.add(boardSquares[j][i] = square);
            }
        }
    }

    public final JComponent getChessBoard() {
    return board;
    }

    public final JComponent getGui() {
        return playArea;
    }

    public static void main(String[] args) {

        GameWindow window = new GameWindow();

        JFrame frame = new JFrame("Checkers");
        frame.setResizable(false);
        frame.add(window.getGui());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationByPlatform(true);
        frame.setSize(800, 800);

        frame.setVisible(true);
    }
}
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
aidandeno
  • 307
  • 1
  • 2
  • 16

2 Answers2

4

Firstly, since JDK 1.4, Java is encouraging the use of BorderLayout constants as BorderLayout.PAGE_START, BorderLayout.LINE_START, BorderLayout.CENTER, BorderLayout.LINE_END and BorderLayout.PAGE_END over the latter used by you.

Secondly you can simply override, the getPreferredSize() of the said JPanel, in order for it to give, some size that you feel like will work for your use case. Use of setPreferredSize() is restricted, since, not all LayoutManagers use to respect the Dimension specified by it.

Hence you could do something like:

private final JPanel sidebar = new JPanel() {
    @Override
    public Dimension getPreferredSize() {
        return new Dimension(100, 100);
    }
};

You can try this modified code:

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

public class GameWindow extends JFrame {

    private final JPanel playArea = new CustomPanel(710, 710);  
    private final JButton[][] boardSquares = new JButton[8][8];
    private final JPanel board;
    private final JPanel sidebar = new CustomPanel(100, 100);
    private final JLabel message = new JLabel("Game by ...");

    public  GameWindow() {
        playArea.setLayout(new BorderLayout(3,3));
        playArea.setBorder(new EmptyBorder(5, 5, 5, 5));

        JToolBar tools = new JToolBar();


        tools.setFloatable(false);
        playArea.add(tools, BorderLayout.PAGE_START);
        tools.add(new JButton("New Game"));
        tools.add(new JButton("Save"));
        tools.add(new JButton("Restore")); 
        tools.addSeparator();
        tools.add(new JButton("Resign"));
        tools.addSeparator();
        tools.add(message);

        board = new CustomPanel(600, 600);
        board.setLayout(new GridLayout(0, 8));
        board.setBorder(new LineBorder(Color.BLACK));
        playArea.add(board, BorderLayout.CENTER);
        playArea.add(sidebar, BorderLayout.LINE_START);

        Insets buttonMargin = new Insets(0,0,0,0);
        for (int i = 0; i < boardSquares.length; i++) {
           for (int j = 0; j < boardSquares[i].length; j++) {
                JButton square = new JButton();
                square.setOpaque(true);
                square.setMargin(buttonMargin);
                if ((i+j)%2 == 0) {
                    square.setBackground(Color.WHITE);
                } 
                else {
                    square.setBackground(Color.BLACK);
                }
                board.add(boardSquares[j][i] = square);
            }
        }
    }

    private class CustomPanel extends JPanel {
        private int width;
        private int height;

        public CustomPanel(int width, int height) {
            this.width = width;
            this.height = height;
            setOpaque(true);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(width, height);
        }
    }

    public final JComponent getChessBoard() {
    return board;
    }

    public final JComponent getGui() {
        return playArea;
    }

    public static void main(String[] args) {

        GameWindow window = new GameWindow();

        JFrame frame = new JFrame("Checkers");
        frame.setResizable(false);
        frame.setContentPane(window.getGui());
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.setLocationByPlatform(true);
        frame.pack();

        frame.setVisible(true);
    }
}

Moreover, before setting the background of JButton, it would be wise to call button.setOpaque(true) property.

nIcE cOw
  • 24,468
  • 7
  • 50
  • 143
1

It's not difficult to set the size of a JPanel. Just call setPreferredSize(). In your case to resize your East JPanel, call:

sidebar.setPreferredSize(new Dimension(200, 200));

After that, your LayoutManager will set the size of your JPanel to 200,200.

To your other JPanel, board: It's impossible to make a Component (like a JPanel) remaining a square. They always fit into rectangles. You would need to make your own subclass of JComponent and only paint everything in the square, and leave the rest transparent. Therefore, overwrite the method JComponent.paintComponent(Graphics).

msrd0
  • 7,816
  • 9
  • 47
  • 82
  • See [Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Swing?](http://stackoverflow.com/q/7229226/418556) (Yes.) – Andrew Thompson Sep 06 '14 at 10:34
  • @AndrewThompson Do think its better to overwrite `getPreferredSize` of the `JPanel` as _nIcE cOw_ suggested? I think its only more code with the same function – msrd0 Sep 06 '14 at 10:40
  • Same function, but better design. – Andrew Thompson Sep 06 '14 at 10:48
  • @AndrewThompson What's better design on it? It's only more code – msrd0 Sep 06 '14 at 10:48
  • @msrd0: Actually, in some situations, `setXxXSize()` might won't be entertained by the `LayoutManager` concern. Though when asked, by the `LayoutManager`, `getPreferredSize()` is bound to give, the right `Dimension` to the calling entity. – nIcE cOw Sep 06 '14 at 11:37