paulschnitzel
paulschnitzel

Reputation: 33

Problem with Java GridLayout and adding Buttons

I want to add 100 buttons into an GridLayout and my code works but sometimes it only adds one button and if I click where the other buttons belong the button where I clicked appears. it happens totally randomly and I don't get it. Here is my code:

    public class GamePanel extends JPanel {
    GameUI controler;
    GridLayout gameLayout = new GridLayout(10,10);
    JButton gameButtons[] = new JButton[100];
    ImageIcon ice;
    JButton startButton;
    JButton exitButton;
    ImageIcon startIcon;
    ImageIcon exitIcon;
    URL urlIcon;
    private int i;

    public GamePanel(GameUI controler) {
        this.setLayout(gameLayout);
        this.controler = controler;
        urlIcon = this.getClass().getResource("/icons/Overlay.png");
        ice = new ImageIcon(urlIcon);
        makeButtons();
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);
    }

    public void makeButtons() {
        for(i = 0; i< 100; i++) {
            gameButtons[i] = new JButton(ice);
            this.add(gameButtons[i]);
            revalidate();   
        }
        repaint();
    }
}

update:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;

import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.net.URL;


public class GameUI extends JFrame {

ImageIcon i;
Image jFrameBackground;
JButton startButton;
JButton exitButton;
ImageIcon startIcon; 
ImageIcon exitIcon;


public GameUI() {
    setResizable(false);
    this.setSize(1200, 800);
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    this.setLayout(null);








    BackGroundPanel backGroundPanel = new BackGroundPanel();
    GamePanel panel = new GamePanel(this);
    ButtonPanel buttonPanel = new ButtonPanel();

    panel.setSize(500,500);
    panel.setLocation(100, 150);
    backGroundPanel.setSize(this.getWidth(),this.getHeight());
    backGroundPanel.setLocation(0,0);
    buttonPanel.setSize(390,50);
    buttonPanel.setLocation(100,100);
    this.add(backGroundPanel);
    this.add(panel);
    this.add(buttonPanel);




    backGroundPanel.setBackground(Color.BLACK);



}





public static void main(String[] args) throws InvocationTargetException, InterruptedException {







    javax.swing.SwingUtilities.invokeAndWait(
                new Runnable(){

                    @Override
                    public void run() {



                        GameUI ui = new GameUI();
                        ui.setVisible(true);


                    }


                }

            );




}

}

Upvotes: 1

Views: 860

Answers (1)

Hovercraft Full Of Eels
Hovercraft Full Of Eels

Reputation: 285403

As I mentioned in comments, you're using a null layout, and this is the source of your problems.

You're using the null layout to try to layer JPanels, one on top of the other, and that is not how it should be used or what it is for, nor how you should create backgrounds. This is having the effect of the background covering your buttons until your mouse hovers over them.

Instead if you wish to create a background image, I would recommend that you:

  • create a JPanel, say called BackgroundPanel,
  • override its paintComponent method,
  • call its super.paintComponent(g); on your method's first line
  • then draw the image it should display
  • then give it a decent layout manager
  • and add your GUI components to it
  • Make sure that any JPanels added to it are made transparent via .setOpaque(false)

Other options include using a JLayeredPane, but you really don't need this just to have a background.

For example, the following code produces:

enter image description here

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;

public class GameUI2 {

    private static final String IMG_PATH = "https://upload.wikimedia.org/wikipedia/commons/3/3f/"
            + "Butterfly_Nebula_in_narrow_band_Sulfur%2C_Hydrogen_and_Oxygen_Stephan_Hamel.jpg";
    private static final String BTN_IMG_PATH = "https://upload.wikimedia.org/wikipedia/commons/5/54/Crystal_Project_Games_kids.png";

    private static void createAndShowGui() {
        BufferedImage bgImg = null;
        BufferedImage btnImg = null;
        try {
            URL bgImgUrl = new URL(IMG_PATH);
            URL btnImgUrl = new URL(BTN_IMG_PATH);
            bgImg = ImageIO.read(bgImgUrl);
            btnImg = ImageIO.read(btnImgUrl);
        } catch (IOException e) {
            e.printStackTrace();
            System.exit(-1);
        }


        BackgroundPanel2 mainPanel = new BackgroundPanel2(bgImg);
        mainPanel.setLayout(new GridBagLayout());
        GamePanel2 gamePanel = new GamePanel2(btnImg); 
        mainPanel.add(gamePanel);        

        JFrame frame = new JFrame("Game");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.setResizable(false);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }
}

@SuppressWarnings("serial")
class BackgroundPanel2 extends JPanel {
    private Image backgroundImg;

    public BackgroundPanel2(Image backgroundImg) {
        this.backgroundImg = backgroundImg;
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        if (backgroundImg != null) {
            g.drawImage(backgroundImg, 0, 0, this);
        }
    }

    @Override
    public Dimension getPreferredSize() {
        if (isPreferredSizeSet() || backgroundImg == null) {
            return super.getPreferredSize();
        } else {
            int w = backgroundImg.getWidth(this);
            int h = backgroundImg.getHeight(this);
            return new Dimension(w, h);
        }
    }
}

@SuppressWarnings("serial")
class GamePanel2 extends JPanel {
    public static final int MAX_BUTTONS = 100;
    private static final int IMG_WIDTH = 40;
    JButton[] gameButtons = new JButton[MAX_BUTTONS];

    public GamePanel2(Image buttonImg) {
        setOpaque(false);
        if (buttonImg.getWidth(this) > IMG_WIDTH) {
            buttonImg = buttonImg.getScaledInstance(IMG_WIDTH, IMG_WIDTH, Image.SCALE_SMOOTH);
        }
        Icon icon = new ImageIcon(buttonImg);
        setLayout(new GridLayout(10, 10, 4, 4));
        for (int i = 0; i < gameButtons.length; i++) {
            int finalIndex = i;
            JButton btn = new JButton(icon);
            btn.addActionListener(e -> {
                String text = String.format("Button: %02d", finalIndex);
                System.out.println(text);
            });
            add(btn);
            gameButtons[i] = btn;            
        }
    }
}

Upvotes: 2

Related Questions