Search code examples
javaswingjpaneljbutton

JButtons aren't placed at the same location than their JPanel


I am trying to make a sudoku grid for now. So I use 2 arrays (double dimensions) one containing all the JButtons and the other one containing 9 JPanels. I placed 9 buttons in each JPanel, I used a GridLayout of (3,3) into each JPanel and all the JPanels are in a bigger JPanel which is using a gridLayout too. The problem is that the buttons are at the bottom of the window so not all of them are displayed. I set a green background for the first JPanel (containing the first 9 buttons) to see where it was compared to its buttons. And I cannot resize the buttons nor the panels.

Here a screen of the HMI

Here the code of my class:

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Sudoku extends JFrame implements ActionListener {


    public Sudoku(){
        //Initialise the window and show it
        this.setTitle("Sudoku Solver");
        this.setSize(1000, 500);
        this.setLocationRelativeTo(null);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel pan = new JPanel();
        pan.setLayout(new GridLayout(3,3));

        //Initialise an array of JPanel
        JPanel[][] jPanelTab = new JPanel[3][3];
        for(int i = 0; i < 3;i++){
            for(int j = 0; j < 3;j++){
                jPanelTab[i][j] = new JPanel();
                jPanelTab[i][j].setLayout(new GridLayout(3,3));
            }
        }


        //Initialise the JButtons
        JButton[][] boutonTab = new JButton[9][9];
        for(int i = 0; i < 9;i++){
            for(int j = 0; j < 9;j++){
                boutonTab[i][j] = new JButton();
                boutonTab[i][j].setText(""+i+"/"+j);
            }
        }


        for(int h = 0; h < 3; h++) {
            int n = 0;
            for (int i = 0; i < 3; i++) {
                int column = 0;
                for (int j = 0; j < 9; j++) {
                    jPanelTab[h][column].add(boutonTab[n][j]);
                    if (j == 2 || j == 5) {
                        column++;
                    }
                }
                n++;
            }
        }

        //Add the 9 JPanels to the JFrame
        for(int i = 0; i < 3;i++){
            for(int j = 0; j < 3;j++){
                if(j == 0 && i == 0)
                    pan.add(jPanelTab[i][j]).setBackground(Color.green);
                else
                    pan.add(jPanelTab[i][j]);

            }
        }
        this.setContentPane(pan);
        this.setVisible(true);

    }

    @Override
    public void actionPerformed(ActionEvent e) {

    }
}

Thanks for your answers!


Solution

  • When dealing with 2D arrays the first index is the row and the second index is the column.

    So using better variable names may help understand the looping logic. In my code below I have use variables containing "r" (row) and "c" (column).

    When using the above variable names in your looping code you now loop through the rows before the columns, so the outer loop will contain "r" in the variable name and the inner loop will contain "c" in the variable name.

    Hopefully when you read the code it will become easier to understand.

    The main change made to the code is the logic that is used to add the individual buttons to each of the 9 panels.

    Notice how the starting indexes for the buttons are 3 times the indexes for the panels. The column and row indexes must be reset for every 3rd button added to the panel.

    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    
    public class Sudoku extends JFrame {
    
        public Sudoku(){
    
            //Initialise the window and show it
            this.setTitle("Sudoku Solver");
            this.setSize(1000, 500);
            this.setLocationRelativeTo(null);
            this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
            JPanel board = new JPanel();
            board.setLayout(new GridLayout(3,3));
    
            //Initialise an array of JPanel
            JPanel[][] panels = new JPanel[3][3];
            for (int r = 0; r < 3; r++)
            {
                for (int c = 0; c < 3; c++)
                {
                    JPanel panel = new JPanel( new GridLayout(3, 3) );
                    panels[r][c] = panel;
                    board.add( panel );
                }
            }
    
            //Initialise the JButtons
            JButton[][] buttons = new JButton[9][9];
            for(int r = 0; r < 9; r++)
            {
                for(int c = 0; c < 9; c++)
                {
                    buttons[r][c] = new JButton(r + "/" + c);
                }
            }
    
            for (int panelR = 0; panelR < 3; panelR++)
            {
                for (int panelC = 0; panelC < 3; panelC++)
                {
                    int buttonR = panelR * 3;
                    int buttonC = panelC * 3;
    
                    for (int i = 0; i < 9; i++)
                    {
                        panels[panelR][panelC].add(buttons[buttonR][buttonC]);
                        buttonC++;
    
                        if ((i + 1) % 3 == 0)
                        {
                            buttonC = panelC * 3;
                            buttonR++;
                        }
                    }
                }
            }
    
            this.setContentPane(board);
            this.setVisible(true);
    
        }
    
        public static void main(String[] args) throws Exception
        {
            java.awt.EventQueue.invokeLater( () -> new Sudoku() );
        }
    }