Gap between JPanels in GridLayout - java

The code below produces nine individual JPanels in which are 9 buttons. The nine JPanels are arranged onto a base JPanel using GridLayout. This base JPanel is then placed onto the ContentPane using Border Layout. I'm using borders for the JButtons and each individual JPanel to clearly define their separation. The JButtons inside each JPanel look fine but there is a gap between the JPanels which is causing the appearance of a double line which is bugging the hell out of me. I've tried adding each individual JPanel onto the ContentPane directly but this does nothing. Totally stumped and wondering if anyone has any suggestions?
P.S. I know the mass of duplicate code needs re-factoring in a bad way and it will, this is just for mock-up purposes.
Thanks,
import java.awt.*;
import javax.swing.*;
import javax.swing.UIManager.*;
public class View1 extends JFrame
{
private JPanel basePanel;
private JPanel childPanel1;
private JPanel childPanel2;
private JPanel childPanel3;
private JPanel childPanel4;
private JPanel childPanel5;
private JPanel childPanel6;
private JPanel childPanel7;
private JPanel childPanel8;
private JPanel childPanel9;
private int row = 3;
private int column = 3;
private JButton[][] squares1;
private JButton[][] squares2;
private JButton[][] squares3;
private JButton[][] squares4;
private JButton[][] squares5;
private JButton[][] squares6;
private JButton[][] squares7;
private JButton[][] squares8;
private JButton[][] squares9;
private Font numberFont;
public View1()
{
setSize(400,400);
setTitle("2013");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
basePanel = new JPanel();
basePanel.setLayout(new GridLayout(row, column, 0, 0));
numberFont = new Font("sansserif", Font.BOLD, 32);
childPanel1Setup();
childPanel2Setup();
childPanel3Setup();
childPanel4Setup();
childPanel5Setup();
childPanel6Setup();
childPanel7Setup();
childPanel8Setup();
childPanel9Setup();
basePanel.add(childPanel1);
basePanel.add(childPanel2);
basePanel.add(childPanel3);
basePanel.add(childPanel4);
basePanel.add(childPanel5);
basePanel.add(childPanel6);
basePanel.add(childPanel7);
basePanel.add(childPanel8);
basePanel.add(childPanel9);
Container cp = getContentPane();
cp.setLayout(new BorderLayout());
cp.add(basePanel, BorderLayout.CENTER);
}
public void childPanel1Setup()
{
childPanel1 = new JPanel();
childPanel1.setLayout(new GridLayout(row, column, 0, 0));
childPanel1.setBorder(BorderFactory.createLineBorder(Color.BLACK));
squares1 = new JButton[row][column];
for(int rows = 0; rows < this.row; rows++)
{
for(int cols = 0; cols < this.column; cols++)
{
squares1[rows][cols] = new JButton();
squares1[rows][cols].setSize(32, 32);
squares1[rows][cols].setBorder(BorderFactory.createLineBorder(Color.BLACK));
squares1[rows][cols].setBackground(Color.WHITE);
childPanel1.add(squares1[rows][cols]);
}
}
}
public void childPanel2Setup()
{
childPanel2 = new JPanel();
childPanel2.setLayout(new GridLayout(row, column, 0, 0));
childPanel2.setBorder(BorderFactory.createLineBorder(Color.BLACK));
squares2 = new JButton[row][column];
for(int rows = 0; rows < this.row; rows++)
{
for(int cols = 0; cols < this.column; cols++)
{
squares2[rows][cols] = new JButton();
squares2[rows][cols].setSize(32, 32);
squares2[rows][cols].setBorder(BorderFactory.createLineBorder(Color.BLACK));
squares2[rows][cols].setBackground(Color.WHITE);
childPanel2.add(squares2[rows][cols]);
}
}
}
public void childPanel3Setup()
{
childPanel3 = new JPanel();
childPanel3.setLayout(new GridLayout(row, column, 0, 0));
childPanel3.setBorder(BorderFactory.createLineBorder(Color.BLACK));
squares3 = new JButton[row][column];
for(int rows = 0; rows < this.row; rows++)
{
for(int cols = 0; cols < this.column; cols++)
{
squares3[rows][cols] = new JButton();
squares3[rows][cols].setSize(32, 32);
squares3[rows][cols].setBorder(BorderFactory.createLineBorder(Color.BLACK));
squares3[rows][cols].setBackground(Color.WHITE);
childPanel3.add(squares3[rows][cols]);
}
}
}
public void childPanel4Setup()
{
childPanel4 = new JPanel();
childPanel4.setLayout(new GridLayout(row, column, 0, 0));
childPanel4.setBorder(BorderFactory.createLineBorder(Color.BLACK));
squares4 = new JButton[row][column];
for(int rows = 0; rows < this.row; rows++)
{
for(int cols = 0; cols < this.column; cols++)
{
squares4[rows][cols] = new JButton();
squares4[rows][cols].setSize(32, 32);
squares4[rows][cols].setBorder(BorderFactory.createLineBorder(Color.BLACK));
squares4[rows][cols].setBackground(Color.WHITE);
childPanel4.add(squares4[rows][cols]);
}
}
}
public void childPanel5Setup()
{
childPanel5 = new JPanel();
childPanel5.setLayout(new GridLayout(row, column, 0, 0));
childPanel5.setBorder(BorderFactory.createLineBorder(Color.BLACK));
squares5 = new JButton[row][column];
for(int rows = 0; rows < this.row; rows++)
{
for(int cols = 0; cols < this.column; cols++)
{
squares5[rows][cols] = new JButton();
squares5[rows][cols].setSize(32, 32);
squares5[rows][cols].setBorder(BorderFactory.createLineBorder(Color.BLACK));
squares5[rows][cols].setBackground(Color.WHITE);
childPanel5.add(squares5[rows][cols]);
}
}
}
public void childPanel6Setup()
{
childPanel6 = new JPanel();
childPanel6.setLayout(new GridLayout(row, column, 0, 0));
childPanel6.setBorder(BorderFactory.createLineBorder(Color.BLACK));
squares6 = new JButton[row][column];
for(int rows = 0; rows < this.row; rows++)
{
for(int cols = 0; cols < this.column; cols++)
{
squares6[rows][cols] = new JButton();
squares6[rows][cols].setSize(32, 32);
squares6[rows][cols].setBorder(BorderFactory.createLineBorder(Color.BLACK));
squares6[rows][cols].setBackground(Color.WHITE);
childPanel6.add(squares6[rows][cols]);
}
}
}
public void childPanel7Setup()
{
childPanel7 = new JPanel();
childPanel7.setLayout(new GridLayout(row, column, 0, 0));
childPanel7.setBorder(BorderFactory.createLineBorder(Color.BLACK));
squares7 = new JButton[row][column];
for(int rows = 0; rows < this.row; rows++)
{
for(int cols = 0; cols < this.column; cols++)
{
squares7[rows][cols] = new JButton();
squares7[rows][cols].setSize(32, 32);
squares7[rows][cols].setBorder(BorderFactory.createLineBorder(Color.BLACK));
squares7[rows][cols].setBackground(Color.WHITE);
childPanel7.add(squares7[rows][cols]);
}
}
}
public void childPanel8Setup()
{
childPanel8 = new JPanel();
childPanel8.setLayout(new GridLayout(row, column, 0, 0));
childPanel8.setBorder(BorderFactory.createLineBorder(Color.BLACK));
squares8 = new JButton[row][column];
for(int rows = 0; rows < this.row; rows++)
{
for(int cols = 0; cols < this.column; cols++)
{
squares8[rows][cols] = new JButton();
squares8[rows][cols].setSize(32, 32);
squares8[rows][cols].setBorder(BorderFactory.createLineBorder(Color.BLACK));
squares8[rows][cols].setBackground(Color.WHITE);
childPanel8.add(squares8[rows][cols]);
}
}
}
public void childPanel9Setup()
{
childPanel9 = new JPanel();
childPanel9.setLayout(new GridLayout(row, column, 0, 0));
childPanel9.setBorder(BorderFactory.createLineBorder(Color.BLACK));
squares9 = new JButton[row][column];
for(int rows = 0; rows < this.row; rows++)
{
for(int cols = 0; cols < this.column; cols++)
{
squares9[rows][cols] = new JButton();
squares9[rows][cols].setSize(32, 32);
squares9[rows][cols].setBorder(BorderFactory.createLineBorder(Color.BLACK));
squares9[rows][cols].setBackground(Color.WHITE);
childPanel9.add(squares9[rows][cols]);
}
}
}
}

I believe it's because the Layout Manager for JPanels is FlowLayout which includes a margin. When you create the panels, set their layout to GridLayout which will give you 0 margin.
Also have you done setVgap(0); and setHgap(0); for the GridLayout?

GridLayout makes all component to be of the same size. If it needs to layout matrix of 3x3 components inside JPanel that it 100x100 pixels, each component will be 33x33 pixels and there will be on extra pixel at the right and at the bottom because 100 is not factor of 3. If JPanel is 101x101 pixels, there will be extra pixels at all four edges.
Consider using GridBagLayout or Box or some other layout that is smarter than GridLayout.

Related

using SpringUtilities and SpringLayout cannot add another component(JPanel) to JFrame

panel code derive from oracle docs(https://docs.oracle.com/javase/tutorial/uiswing/layout/spring.html). I want add a clear button to the same frame, So I created another panel: panel1. Now the situation is panel and panel1, the code will only show one of the panel. While running code, I want panel1 above the panel. Please tell me how to make it happen? The SpringLayout and SpringUtilities works very well.
import javax.swing.*;
import java.awt.*;
public class SpringDemo1 {
public static void createAndShowGUI() {
JFrame springlayoutFrame = new JFrame("Springlayout Demo");
JPanel panel = new JPanel(new SpringLayout());
JPanel panel1 = new JPanel(new SpringLayout());
JRadioButton jRadioButton = new JRadioButton("Clear");
panel1.add(jRadioButton);
int rows = 5;
int cols = 10;
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
int anInt = (int) Math.pow(r, c);
JTextField jTextField1 = new JTextField(Integer.toString(anInt));
panel.add(jTextField1);
}
}
SpringUtilities.makeCompactGrid(panel, //parent
rows, cols,
10, 50, //initX, initY
3, 3); //xPad, yPad
//SpringUtilities.makeCompactGrid(panel1,1,1,0,50,5,5);
panel.setOpaque(true);
panel1.setOpaque(true);
//springlayoutFrame.setContentPane(panel);
springlayoutFrame.getContentPane().add(panel);
//springlayoutFrame.getContentPane().add(panel1);
springlayoutFrame.pack();
springlayoutFrame.setVisible(true);
}
}

making a chessboard with arrays of JPanel

I 'm doing a chessboard , my idea is to make an array of JPanels , each box is a JPanel with color, the problem I have , when I make such assignment
" chessboard [ rows ] [columns ] = b" and compile gives me an exception .
Why the assignment gives me an error ?
How I can fix it?
Is the layout grid , should go in the JFrame or JPanel ?
thanks.
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
First Class
public class ChessBoard extends JPanel {
private JPanel[][] chessBoardSquares = new JPanel[8][8];
private final JPanel tile;
public ChessBoard () {
tile = new JPanel();
tile.setLayout(new GridLayout(8, 8));
for (int rows = 0; rows < 8; rows++) {
for (int columns = 0;columns< 8;columns++) {
JPanel b = new JPanel();
chessBoardSquares = new JPanel[rows][columns];
if ((rows+columns +1)%2 == 0){
b.setBackground(Color.WHITE);
chessBoardSquares[rows][columns] = b;
}
tile.add( chessBoardSquares [rows][columns]);
}
}
}
}
main
public class example {
public static void main(String[] args) {
JFrame window = new JFrame();
ChessBoard chessBoard = new ChessBoard();
window.add( chessBoard );
window.setVisible(true);
}
}
You're not filling your array properly.
This
for (int rows = 0; rows < 8; rows++) {
for (int columns = 0;columns< 8;columns++) {
JPanel b = new JPanel();
// ***** this creates a completely new array *******
chessBoardSquares = new JPanel[rows][columns];
should be
for (int rows = 0; rows < 8; rows++) {
for (int columns = 0;columns< 8;columns++) {
JPanel b = new JPanel();
// this assigns a JPanel to an array item
chessBoardSquares[rows][columns] = new JPanel();
Also as an aside, I don't see where you're adding the tile JPanel to your GUI, and you'll want to fix this.
It should be better like this :
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class ChessBoard extends JPanel {
private final JPanel[][] tiles = new JPanel[8][8];
public ChessBoard() {
Dimension dims = new Dimension(64, 64);
setLayout(new GridLayout(8, 8));
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
JPanel b = new JPanel();
b.setPreferredSize(dims);
b.setMinimumSize(dims);
if ((i + j + 1) % 2 == 0) {
b.setBackground(Color.WHITE);
} else {
b.setBackground(Color.BLACK);
}
add(b);
tiles[i][j] = b;
}
}
}
public static void main(String[] args) {
JFrame f = new JFrame("Chess");
ChessBoard chessBoard = new ChessBoard();
f.add(chessBoard);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}

Creating Grid on my Image

I am currently trying to create a moving character in a Map using AWT and Swings.
I need help on trying to create a GridLayout on my Image. I have tried using setLayout(new GridLayout()) and it just doesn't work.
If possible, I would also like to incorporate a KeyListener to this.
Currently, Here's my Code for the Image:
public class GUI extends JFrame{
GUI(){
setLayout(new FlowLayout());
ImageIcon image1 = new ImageIcon("path-to-backgroundImage");
JLabel label1 = new JLabel(image1);
add(label1);
}
public static void main(String[] args) {
GUI gui = new GUI();
gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
gui.setVisible(true);
gui.pack();
gui.setTitle("Map");
}
}
And Here's the GridLayout I had with the code, but it doesn't work:
setLayout(new GridLayout(ROWS, COLS));
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
JLabel label = new JLabel(cellIcon);
add(label);
}
}
Help is always highly appreciated!
JLabel label1 = new JLabel(image1);
add(label1);
You add the label to the frame, which is reasonable:
setLayout(new GridLayout(ROWS, COLS));
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
JLabel label = new JLabel(cellIcon);
add(label);
}
}
But then you change the layout of the frame and add more labels to the frame. Your code doesn't make sense. If you want to add the grid of labels to the background image then the code should be:
label1.setLayout(new GridLayout(ROWS, COLS));
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
JLabel label = new JLabel(cellIcon);
label1.add(label);
}
}
If you need more help then poste a proper SSCCE that demonstrates the problem. The random lines of code don't tell us the context of how the code is used.

Add JLabel Array to JPanel

I created a JPanel Grid and now I want add Array of image Slices to Grid with loop
in last line I have error.
public static final int WIDTH = 1024;
public static final int HEIGHT = 640;
private static final int GRID_ROWS = 20;
private static final int GRID_COLS = 20;
private static final int GAP = 1;
private static final Dimension LAYERED_PANE_SIZE = new Dimension(WIDTH, HEIGHT);
private static final Dimension LABEL_SIZE = new Dimension(60, 40);
private GridLayout gridlayout = new GridLayout(GRID_ROWS, GRID_COLS, GAP, GAP);
private JPanel backingPanel = new JPanel(gridlayout);
private JPanel[][] panelGrid = new JPanel[GRID_ROWS][GRID_COLS];
private JLabel redLabel = new JLabel("Red", SwingConstants.CENTER);
private JLabel blueLabel = new JLabel("Blue", SwingConstants.CENTER);
// code in constructor
backingPanel.setSize(LAYERED_PANE_SIZE);
backingPanel.setLocation(2 * GAP, 2 * GAP);
backingPanel.setBackground(Color.black);
for (int row = 0; row < GRID_ROWS; row++) {
for (int col = 0; col < GRID_COLS; col++) {
panelGrid[row][col] = new JPanel(new GridBagLayout());
backingPanel.add(panelGrid[row][col]);
}
}
setLayout(new GridLayout(GRID_ROWS, GRID_COLS));
BufferedImage bi = null;
try {
bi = ImageIO.read(new File("assets/image.jpg"));
} catch (IOException e) {
e.printStackTrace();
}
for (int r = 0; r < GRID_ROWS; r++) {
for (int c = 0; c < GRID_COLS; c++) {
int w = bi.getWidth() / GRID_ROWS;
int h = bi.getHeight() / GRID_COLS;
BufferedImage b = bi.getSubimage(c * w, r * h, w, h);
list.add(new JLabel(new ImageIcon(b)));
panelGrid[r][c] = new JPanel(new GridBagLayout());
backingPanel.add(panelGrid[r][c]);
panelGrid[r][c].add(list.get(r));
}
}
Since list is an instance of List, and Java is not C++, you cant specify methods like operator[]. You need to use list.get(), like this:
panelGrid[r][c].add(list.get(r));
Also, you should use a GridBagLayout with GridBagConstraints. Therefore, call
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
And change the lines where you add the panel to this:
panelGrid[r][c] = new JPanel(new GridBagLayout());
panelGrid[r][c].add(list.get(r));
gbc.gridx = r; gbc.gridy = c;
backingPanel.add(panelGrid[r][c], gbc);

Sudoku Board Using JPanels in Java

I know there have been several posts already about Sudoku-related questions, but I am not sure any of them have exactly what I am looking for...
I am trying to build an empty Sudoku board in Java using JPanels and JTextfields. I also need to create a menu on the right hand side with another JPanel.
The board itself is a 9 x 9 square, divided into 9 3x3 squares. Note that each smaller square is set off by a heavier border than the regular intersquare borders. Each square is a text field. Write the program so that nothing is in a text field. Users can type in the text field if they want, and if they do, numbers will show up. On the side there are four buttons that allow you to solve, get a new puzzle, get a hint, or reset puzzle.
Any ideas would be great. I am having trouble understanding how to nest the for loops to create the board. Here is my code...
import javax.swing.*;
import javax.swing.border.Border;
import java.awt.*;
public class ArrayTest extends JFrame {
public ArrayTest() {
JPanel board = new JPanel(new GridLayout(9, 9));
add(board);
JPanel[][] squares = new JPanel[9][9];
Border border = BorderFactory.createLineBorder(Color.BLACK);
for (int row = 1; row < 9; row++) {
for (int col = 1; col < 9; col++) {
squares[row][col] = new JPanel();
board.add(squares[row][col]);
}
}
JPanel menu = new JPanel();
menu.add(new JButton("Reset"));
menu.add(new JButton("Hint"));
menu.add(new JButton("Solve"));
menu.add(new JButton("New Puzzle"));
add(menu);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
/** Create a frame and set its properties*/
JFrame frame = new ArrayTest();
frame.setTitle("Sudoku");
frame.setSize(600, 600);
frame.setLocationRelativeTo(null); //Center the frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
A couple of things I see:
I don't think you want 9x9 JPanels as you have now, but 9x9 JTextFields. You may want 3x3 JPanels so you can make the borders of each section bolder. It might be easier to just lay these out explicitly instead of trying to do it in a loop.
Your loop counters (and array indices) should start at 0, not 1. The way you have it now, the loops will only execute 8 times.
You are going to want to keep track of values in each row, column, and in each 3x3 sub-group. Rows and columns are easy the way you have it in a 2D array. You might consider another array of arrays that hold the values in each 3x3 area. This makes it easier to scan through these values when you need to, and might be useful for placing values in the smaller 3x3 JPanels, if you go that route.
Firstly, I would use some kind of model to control the values within a "virtual" board, this will separate the logic from the UI and allow either to change without adversely effecting the other.
I would provide appropriate event with the model to allow the UI to be updated when the model changes as well as providing a means for each field to update the model as required.
I would then reduce the problem to it's smallest conceptional component, which would be the sub board, and generate the UI to represent it in the most abstract manner I could. This allows for re-use and helps with debugging, as if one board has an issue, then you can fix it in one place for all.
public class Sudoku {
public static void main(String[] args) {
new Sudoku();
}
public Sudoku() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new SudokuBoard());
frame.add(new MenuPane(), BorderLayout.AFTER_LINE_ENDS);
frame.pack();
frame.setVisible(true);
}
});
}
public class MenuPane extends JPanel {
public MenuPane() {
setBorder(new EmptyBorder(4, 4, 4, 4));
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 1;
gbc.weightx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
add(new JButton("Solve"), gbc);
gbc.gridy++;
add(new JButton("New"), gbc);
gbc.gridy++;
add(new JButton("Hint"), gbc);
gbc.gridy++;
add(new JButton("Reset"), gbc);
}
}
public class SudokuBoard extends JPanel {
public static final int ROWS = 3;
public static final int COLUMNS = 3;
private SubBoard[] subBoards;
public SudokuBoard() {
setBorder(new EmptyBorder(4, 4, 4, 4));
subBoards = new SubBoard[ROWS * COLUMNS];
setLayout(new GridLayout(ROWS, COLUMNS, 2, 2));
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLUMNS; col++) {
int index = (row * ROWS) + col;
SubBoard board = new SubBoard();
board.setBorder(new CompoundBorder(new LineBorder(Color.GRAY, 3), new EmptyBorder(4, 4, 4, 4)));
subBoards[index] = board;
add(board);
}
}
}
}
public class SubBoard extends JPanel {
public static final int ROWS = 9;
public static final int COLUMNS = 9;
private JTextField[] fields;
public SubBoard() {
setLayout(new GridLayout(ROWS, COLUMNS, 2, 2));
fields = new JTextField[ROWS * COLUMNS];
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLUMNS; col++) {
int index = (row * COLUMNS) + col;
JTextField field = new JTextField(4);
fields[index] = field;
// field.setText(Integer.toString(index));
add(field);
}
}
}
}
}
UPDATED
To limit the text fields to only allow numeric values to be entered, you can take a look at JTextField limiting character amount input and accepting numeric only for some ideas
UPDATED (with 2D arrays)
Here's a implementation that uses 2D arrays, it also sub groups the sub boards so that each grid of 3x3 fields has it's own board...
public class Sudoku {
public static void main(String[] args) {
new Sudoku();
}
public Sudoku() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new SudokuBoard());
frame.add(new MenuPane(), BorderLayout.AFTER_LINE_ENDS);
frame.pack();
frame.setVisible(true);
}
});
}
public class MenuPane extends JPanel {
public MenuPane() {
setBorder(new EmptyBorder(4, 4, 4, 4));
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 1;
gbc.weightx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
add(new JButton("Solve"), gbc);
gbc.gridy++;
add(new JButton("New"), gbc);
gbc.gridy++;
add(new JButton("Hint"), gbc);
gbc.gridy++;
add(new JButton("Reset"), gbc);
}
}
public class SudokuBoard extends JPanel {
public static final int ROWS = 3;
public static final int COLUMNS = 3;
private SubBoard[][] subBoards;
public SudokuBoard() {
setBorder(new EmptyBorder(4, 4, 4, 4));
subBoards = new SubBoard[ROWS][COLUMNS];
setLayout(new GridLayout(ROWS, COLUMNS, 2, 2));
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLUMNS; col++) {
int index = (row * ROWS) + col;
SubBoard board = new SubBoard();
board.setBorder(new CompoundBorder(new LineBorder(Color.GRAY, 3), new EmptyBorder(4, 4, 4, 4)));
subBoards[row][col] = board;
add(board);
}
}
}
}
public class SubBoard extends JPanel {
public SubBoard() {
setLayout(new GridLayout(3, 3, 2, 2));
for (int index = 0; index < 3*3; index++) {
add(new ChildBoard(3, 3));
}
}
}
public class ChildBoard extends JPanel {
private JTextField[][] fields;
public ChildBoard(int rows, int cols) {
setBorder(new LineBorder(Color.LIGHT_GRAY));
setLayout(new GridLayout(rows, cols, 2, 2));
fields = new JTextField[rows][cols];
for (int row = 0; row < rows; row++) {
for (int col = 0; col < cols; col++) {
JTextField field = new JTextField(4);
fields[row][col] = field;
add(field);
}
}
}
}
}
or, if you want to try and keep all the fields in a single top level reference you could do something like...
public class SubBoard extends JPanel {
private JTextField[][] fields;
public SubBoard() {
setLayout(new GridLayout(3, 3, 2, 2));
fields = new JTextField[9][9];
for (int row = 0; row < 9; row++) {
for (int col = 0; col < 9; col++) {
fields[row][col] = new JTextField(4);
}
}
for (int row = 0; row < 3; row++) {
for (int col = 0; col < 3; col++) {
int startRow = row * 3;
int startCol = col * 3;
add(new ChildBoard(3, 3, fields, startRow, startCol));
}
}
}
}
public class ChildBoard extends JPanel {
public ChildBoard(int rows, int cols, JTextField[][] fields, int startRow, int startCol) {
setBorder(new LineBorder(Color.LIGHT_GRAY));
setLayout(new GridLayout(rows, cols, 2, 2));
for (int row = 0; row < rows; row++) {
for (int col = 0; col < cols; col++) {
JTextField field = fields[startRow + row][startCol + col];
fields[row][col] = field;
add(field);
}
}
}
}
UPDATED with single class
Okay, so rather then sub-classing, simple use a couple of methods to create each individual section of the board, from which you can make repeated calls to...
Remember, reduce and reuse.
public class Sudoku {
public static void main(String[] args) {
new Sudoku();
}
public Sudoku() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new SudokuBoard());
frame.add(new MenuPane(), BorderLayout.AFTER_LINE_ENDS);
frame.pack();
frame.setVisible(true);
}
});
}
public class MenuPane extends JPanel {
public MenuPane() {
setBorder(new EmptyBorder(4, 4, 4, 4));
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 1;
gbc.weightx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
add(new JButton("Solve"), gbc);
gbc.gridy++;
add(new JButton("New"), gbc);
gbc.gridy++;
add(new JButton("Hint"), gbc);
gbc.gridy++;
add(new JButton("Reset"), gbc);
}
}
public class SudokuBoard extends JPanel {
public static final int GRID_ROWS = 3;
public static final int GRID_COLUMNS = 3;
public static final int BOARD_ROWS = 9;
public static final int BOARD_COLUMNS = 9;
private JTextField fields[][];
public SudokuBoard() {
setBorder(new EmptyBorder(4, 4, 4, 4));
fields = new JTextField[GRID_ROWS * BOARD_ROWS][GRID_COLUMNS * BOARD_COLUMNS];
setLayout(new GridLayout(GRID_ROWS, GRID_COLUMNS, 2, 2));
for (int row = 0; row < GRID_ROWS; row++) {
for (int col = 0; col < GRID_COLUMNS; col++) {
int startRow = row * GRID_ROWS;
int startCol = col * GRID_COLUMNS;
add(createBoard(fields, startRow, startCol));
}
}
}
protected JPanel createBoard(JTextField fiels[][], int startRow, int startCol) {
JPanel panel = new JPanel(new GridLayout(3, 3, 2, 2));
panel.setBorder(new CompoundBorder(new LineBorder(Color.DARK_GRAY, 2), new EmptyBorder(2, 2, 2, 2)));
for (int row = 0; row < 3; row++) {
for (int col = 0; col < 3; col++) {
int rowIndex = (startRow + row) * 3;
int colIndex = (startCol + col) * 3;
panel.add(createSubBoard(fields, rowIndex, colIndex));
}
}
return panel;
}
protected JPanel createSubBoard(JTextField[][] fields, int startRow, int startCol) {
JPanel panel = new JPanel(new GridLayout(3, 3, 2, 2));
panel.setBorder(new CompoundBorder(new LineBorder(Color.GRAY, 2), new EmptyBorder(2, 2, 2, 2)));
populateFields(fields, startRow, startCol);
for (int row = 0; row < 3; row++) {
for (int col = 0; col < 3; col++) {
panel.add(fields[row + startRow][col + startCol]);
}
}
return panel;
}
protected void populateFields(JTextField[][] fields, int startRow, int startCol) {
for (int row = startRow; row < startRow + 3; row++) {
for (int col = startCol; col < startCol + 3; col++) {
fields[row][col] = new JTextField(4);
}
}
}
}
}

Categories