Search code examples
javaimageuser-interfacelabelpanel

Java GUI paint picture on labels


I want to add a picture that will be in the panel and also on labels but I don't know how to do that.

my code:

JFrame frame = new JFrame();
JPanel panel = new JPanel();
JPanel mainPanel = new JPanel();

panel.setLayout(new GridLayout(5, 5));
for (int i = 0; i < 5; i++) 
    for (int j = 0; j < 5; j++) 
    {
        JLabel label = new JLabel();
        label.setPreferredSize(new Dimension(50, 50));
        label.setBorder(BorderFactory.createLineBorder(Color.BLACK));
        panel.add(label);
    }



mainPanel.add(panel);
frame.add(mainPanel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);

My Picture: https://i.sstatic.net/w0Ssy.png

What I want to make: https://i.sstatic.net/ZLPqF.png


Solution

  • If you're going to use components do to this job, then you're going to need to do some juggling with the layout managers. Because of it's flexibility, I would use GridBagLayout, in fact, I'm pretty sure it's the only inbuilt layout that will allow you to do something like this...

    enter image description here

    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.Graphics;
    import java.awt.GridBagConstraints;
    import java.awt.GridBagLayout;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.border.MatteBorder;
    
    public class Test {
    
        public static void main(String[] args) {
            new Test();
        }
    
        public Test() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    JFrame frame = new JFrame();
                    frame.add(new GamePane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public class GamePane extends JPanel {
    
            public GamePane() {
                setLayout(new GridBagLayout());
                GridBagConstraints gbc = new GridBagConstraints();
                for (int y = 0; y < 10; y++) {
                    for (int x = 0; x < 10; x++) {
                        GridPane gridPane;
                        if (y == 9) {
                            if (x == 9) {
                                gridPane = new GridPane(1, 1, 1, 1);
                            } else {
                                gridPane = new GridPane(1, 1, 1, 0);
                            }
                        } else if (x == 9) {
                            gridPane = new GridPane(1, 1, 0, 1);
                        } else {
                            gridPane = new GridPane(1, 1, 0, 0);
                        }
                        gbc.gridx = x;
                        gbc.gridy = y;
                        add(gridPane, gbc);
                    }
                }
    
                gbc = new GridBagConstraints();
                gbc.gridx = 0;
                gbc.gridy = 0;
                gbc.gridwidth = 1;
                gbc.gridheight = 4;
                gbc.fill = GridBagConstraints.HORIZONTAL;
                add(new ShipPane(1, 4), gbc, 0);
    
                gbc = new GridBagConstraints();
                gbc.gridx = 2;
                gbc.gridy = 1;
                gbc.gridwidth = 3;
                gbc.gridheight = 1;
                gbc.fill = GridBagConstraints.BOTH;
                add(new ShipPane(3, 1), gbc, 0);
            }
    
        }
    
        public class Configuration {
            public static int GRID_SIZE = 50;
        }
    
        public class GridPane extends JPanel {
    
            public GridPane(int top, int left, int bottom, int right) {
                setBorder(new MatteBorder(top, left, bottom, right, Color.DARK_GRAY));
            }
    
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(Configuration.GRID_SIZE, Configuration.GRID_SIZE);
            }
    
        }
    
        public class ShipPane extends JPanel {
    
            private int gridWidth, gridHeight;
    
            public ShipPane(int gridWidth, int gridHeight) {
                this.gridWidth = gridWidth;
                this.gridHeight = gridHeight;
                setOpaque(false);
            }
    
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(Configuration.GRID_SIZE * gridWidth, Configuration.GRID_SIZE * gridHeight);
            }
    
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                g.setColor(new Color(255, 0, 0, 128));
                g.fillRect(0, 0, getWidth(), getHeight());
            }
        }
    }
    

    Now, I'm just using a panel, but without much work, you could add a JLabel to the ShipPane

    Now, having said that. I think I would approach this problem from an entirely "custom painting" route