0

I have issues with the GridLayout i think. I tried to place 25 buttons to the Jpanel "lightJpanel" but all the buttons are only on one at the top left of my lightJpanel. I tried many things but i don't find the issue... The buttons are created but they are not visibles. A solution to resolve the problem ?

Here's what my code currenlty gives me:

enter image description here

Here's my code:

public class Window extends JFrame {

    /**
     * Main JPanel
     */
    private JPanel container = new JPanel();
    /**
     * Message area
     */
    private JLabel screen = new JLabel();
    /**
     * table light
     */
    private Light light[][] = new Light[5][5];
    /**
     * button who allows to configure the start of game
     */
    private JButton configure = new JButton("Configure the lights");
    /**
     * button who allows to start the game
     */
    private JButton play = new JButton("Play");
    /**
     * button who allows to place random lights
     */
    private JButton random = new JButton("Random configuration");
    /**
     * stop button for stop the game
     */
    private JButton stop = new JButton("Stop");


    /**
     * construct a window
     *
     * @param controller the controller of the window
     */
    public Window() {
        this.setSize(500, 500);
        this.setTitle("Game of life");
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setLocationRelativeTo(null);
        this.setResizable(false);
        initComponents();
        this.setContentPane(container);
        this.setVisible(true);
    }

    /**
     * Initialization of graphical components
     */
    private void initComponents() {

        //for the message
        Font font = new Font("Arial", Font.BOLD, 20);
        screen = new JLabel("Game of life");
        screen.setFont(font);
        screen.setForeground(Color.white);

        JPanel panScreen = new JPanel();
        panScreen.setPreferredSize(new Dimension(480, 40));

        JPanel menuButton = new JPanel();
        menuButton.setPreferredSize(new Dimension(480, 100));

        JPanel lightJpanel = new JPanel();
        lightJpanel.setPreferredSize(new Dimension(300, 300));

        //listeners for menu buttons
        MenuListener menuListener = new MenuListener();

        lightJpanel.setLayout(new GridLayout(5, 5, 0, 0));

        for (int i = 0; i < 5; i++) {
            for (int j = 0; j < 5; j++) {
                light[i][j] = new Light(i, j);
                lightJpanel.add(light[i][j]);
            }
        }

        //size button
        stop.setPreferredSize(new Dimension(70, 40));
        play.setPreferredSize(new Dimension(70, 40));
        random.setPreferredSize(new Dimension(200, 40));
        configure.setPreferredSize(new Dimension(200, 40));

        //add listener
        play.addActionListener(menuListener);
        random.addActionListener(menuListener);
        configure.addActionListener(menuListener);
        stop.addActionListener(menuListener);

        //add buttons to JPanel menuButton
        menuButton.add(configure);
        menuButton.add(random);
        menuButton.add(play);
        menuButton.add(stop);

        stop.setEnabled(false);

        //decoration JLabel screen
        panScreen.add(screen);
        panScreen.setBackground(Color.blue);
        panScreen.setBorder(new javax.swing.border.BevelBorder(BevelBorder.RAISED));
        Border borderLine = BorderFactory.createLineBorder(Color.BLACK);
        panScreen.setBorder(borderLine);

        //test jpanel
        lightJpanel.setBackground(Color.CYAN);
        menuButton.setBackground(Color.black);
        container.setBackground(Color.green);

        //positioning different JPanel to main JPanel
        container.add(panScreen);
        container.add(menuButton);
        container.add(lightJpanel);
    }

Here's my Light class :

    import java.awt.Color;

    import javax.swing.JButton;

public class Light extends JButton{

    /**
     * coordonates of the light according to the GridLayout
     */
    private int x;
    /**
     * coordonates of the light according to the GridLayout
     */
    private int y;
    /**
     * define if the light is lit or not
     */
    private boolean lit;

    /**
     * construct a light
     * @param abs the abscissa of the light
     * @param ord the ordered of the light
     */
    public Light(int abs, int ord){
        super();
        this.x = abs;
        this.y = ord;
        // Default color
        this.setBackground(Color.gray);
        this.lit = false;
    }

    public boolean getLit(){
        return lit;
    }

    public int getX(){
        return this.x;
    }
    public int getY(){
        return this.y;
    }

    /**
     * turn on the light
     */
    public void setOn(){
        this.setBackground(Color.green);
        this.lit = true;
    }
    /**
     * turn off the light
     */
    public void setOff(){
        this.setBackground(Color.gray);
        this.lit = false;
    }   

    public void changeState(){
        if(lit)
            setOff();
        else 
            setOn();
    }
}
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433

2 Answers2

1

Absent a compete example, it's hard to say; but you might compare your approach the one shown here, illustrated below. In particular,

  • Verify that Light has the expected preferred size and location.

  • Don't use setPreferredSize() when you really mean to override getPreferredSize(), as shown here.

image

Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
1

What I thought after initially looking into this:

I think there is likely an issue with your Light class.

Having had more time to look into it

The issue is definitely with your Light class.

Specifically, you've overwritten the getY() and getX() methods from Jcomponent and Component. These methods are used when rendering the components, so I think they're what's causing your problems.

What I did was change your light class to look like this:

    //Make the two fields represent the x and y positions in your grid
/**
 * coordonates of the light according to the GridLayout
 */
private int xPositionInGrid;

/**
 * coordonates of the light according to the GridLayout
 */
private int yPositionInGrid;


    //Alter the constructor to set these two new named fields.
/**
 * construct a light
 * @param abs the abscissa of the light
 * @param ord the ordered of the light
 */
public Light( final int abs, final int ord ) {
    super();
    this.xPositionInGrid = abs;
    this.yPositionInGrid = ord;
    // Default color
    setBackground(Color.gray);
    this.lit = false;
}


    //Rename the two methods so they're not overriding the superclass methods anymore.
public int getXPositionInGrid() {
    return this.xPositionInGrid;
}

public int getYPositionInGrid() {
    return this.yPositionInGrid;
}

With the Light class looking like that, I was able to get the following screen, which I believe is what you're expecting:

enter image description here


What follows is my initial proof that the issue is not within the Window class

You say that you're adding 25 buttons, but what you are actually adding is 25 instances of Light

Not having that Light class, I took your Window code and replaced all references to Light with JButton and it worked fine for me. (I also had to remove the instance of MenuListener as I didn't have that class, but that's not related to the issue I don't believe)

Here are the little bits I changed:

//Made these explicit JButtons
private JButton light[][] = new JButton[5][5];



for (int i = 0; i < 5; i++) {
    for (int j = 0; j < 5; j++) {
        //Made these explicit JButtons
        this.light[i][j] = new JButton();
        lightJpanel.add(this.light[i][j]);
    }
}

I also added in a main method just to run everything:

public static void main(final String[] args) {
    final Window window = new Window();
    window.setVisible(true);
}

And this is what I got:(All active JButtons)

enter image description here

Dan Temple
  • 2,736
  • 2
  • 22
  • 39
  • Yes it's worked. But i need the Light classe because i need the coordonates of each Light and the methods that i have created in this class. For exemple i need coordonates for turn off the light when i clicked on and i need that the light around change their stage too. Maybe i can put the light class into my window class but one file for my project is not very clean no ? – Ducdevolpe May 01 '14 at 10:52
  • @Ducdevolpe Oh yeah, of course you need your `Light` class, I don't doubt that. My point here is that your issue is likely within the `Light` class, not your `Window` class. I wonder if your `Light` class just needs to extend JButton, or Component? Could you provide your `Light` class? That would be helpful. – Dan Temple May 01 '14 at 12:35
  • Yes it's probably with the my class Light that i have a problem. But i don't know how make a JButton if my class Light extends Component. I'm novice in java... if Light extends JButton there is no way to fix this problem ? – Ducdevolpe May 01 '14 at 12:47
  • @Ducdevolpe There's always a solution! :) You don't *need* to extend a component type, but that's how I'd go about it. Doing that will give you a bunch of framework functionality for free. So if you extended JButton, your `Light` would already know how to be a component and JPanels would know how to treat them and GridLayouts would know how to display them. As I say, if you provide your Light class, it's likely we'll find a solution. – Dan Temple May 01 '14 at 13:19
  • I've added your Light class into my code and here's what I'm seeing: The Light objects are all there, but they only render when hovered over with the mouse cursor. Also, when I drag the window between my monitors (dual monitor set up) it re-renders and all of the lights disappear again. I don't have a massive amount of time to check, but perhaps these details help you to discover your issue. I am quite certain it lies in you `Light` class now though. – Dan Temple May 01 '14 at 15:13
  • @Ducdevolpe I've had chance to look into this again today. You've probably already solved it, but I've found that you're overriding some superclass methods that relate to the rendering of the component. With those methods renamed, the `Light` class seems to work fine. – Dan Temple May 06 '14 at 10:49
  • Hi, Yes the problem is resolved and it's because i have used the method getX and getY in the Light class, and this method was already use by the superclass. I Just change the name of the method and it work ! Thanks for your help Dan Temple. – Ducdevolpe May 18 '14 at 07:13