Search code examples
javaswingjpaneljlabel

Place JLabel on top of JLabel with image in


I am pretty sure that this question has been asked before, but my case is slightly different as in i am trying to place a JLabel on top of a JLabel acting as a background, I want to display changing numbers using the JLabels and the numbers need to display over the background, however i am a bit of a swing n00b, thanks in advance, Jonathan


Solution

  • Without fully appreciating your requirements, if you simply need to display text over a background image, you'd be better off placing the label on top a custom panel which is capable of painting your background.

    You get the benefit of a layout manager without the mess.

    I'd start by having a read trough Performing Custom Painting and Graphics2D Trail.

    If that seems to daunting, JLabel is actually a type of Container, meaning it can actually 'contain' other components.

    EXAMPLE

    Background pane...

    public class PaintPane extends JPanel {
    
        private Image background;
    
        public PaintPane(Image image) {     
            // This is just an example, I'd prefer to use setters/getters
            // and would also need to provide alignment options ;)
            background = image;            
        }
    
        @Override
        public Dimension getPreferredSize() {
            return background == null ? new Dimension(0, 0) : new Dimension(background.getWidth(this), background.getHeight(this));            
        }
    
        @Override
        protected void paintComponent(Graphics g) {
    
            super.paintComponent(g);
    
            if (background != null) {                
                Insets insets = getInsets();
    
                int width = getWidth() - 1 - (insets.left + insets.right);
                int height = getHeight() - 1 - (insets.top + insets.bottom);
    
                int x = (width - background.getWidth(this)) / 2;
                int y = (height - background.getHeight(this)) / 2;
    
                g.drawImage(background, x, y, this);                
            }
    
        }
    
    }
    

    Constructed with...

    public TestLayoutOverlay() throws IOException { // Extends JFrame...
    
        setTitle("test");
        setLayout(new GridBagLayout());
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    
        PaintPane pane = new PaintPane(ImageIO.read(new File("fire.jpg")));
        pane.setLayout(new BorderLayout());
        add(pane);
    
        JLabel label = new JLabel("I'm on fire");
        label.setFont(label.getFont().deriveFont(Font.BOLD, 48));
        label.setForeground(Color.WHITE);
        label.setHorizontalAlignment(JLabel.CENTER);
        pane.add(label);
    
        pack();
        setLocationRelativeTo(null);
        setVisible(true);
    
    }
    

    And just to show that I'm not bias ;), an example using labels...

    public TestLayoutOverlay() {
    
        setTitle("test");
        setLayout(new GridBagLayout());
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    
        JLabel background = new JLabel(new ImageIcon("fire.jpg"));
        background.setLayout(new BorderLayout());
        add(background);
    
        JLabel label = new JLabel("I'm on fire");
        label.setFont(label.getFont().deriveFont(Font.BOLD, 48));
        label.setForeground(Color.WHITE);
        label.setHorizontalAlignment(JLabel.CENTER);
        background.add(label);
    
        pack();
        setLocationRelativeTo(null);
        setVisible(true);
    
    }
    

    On fire