javaswingbackgroundgifjlayeredpane

Java Swing drawing gif as background to several JButtons and JLabels


I want to draw a gif as background to the starting window of my java project (small game in Java swing for school). Here's my code so far:

package graphic;

import javax.swing.*;
import java.awt.*;
import java.io.File;

//Frame di inizio gioco usato per la selezione del numero di giocatori e la modalità di gioco
public class selectionWindow extends JFrame {

    //Panelli
    private final JPanel logoPanel = new JPanel();
    private final JPanel selectionPanel = new JPanel();
    private final JPanel offlinePanel = new JPanel();
    private final JPanel onlinePanel = new JPanel();
    private final JPanel foregroundPanel = new JPanel();
    private final JPanel backgroundPanel = new JPanel();
    //Componenti offline
    private final JButton offlineButton = new JButton("Offline");
    private final JButton offlineButton_twoPlayer = new JButton("2 Players");
    private final JButton offlineButton_threePlayer = new JButton("3 Players");
    private final JButton offlineButton_fourPlayer = new JButton("4 Players");
    private final Component[] offlineComponents;
    //Componenti online
    private final JButton onlineButton = new JButton("Online");
    private final JButton onlineButton_twoPlayer = new JButton("2 Players");
    private final JButton onlineButton_threePlayer = new JButton("3 Players");
    private final JButton onlineButton_fourPlayer = new JButton("4 Players");
    private final JButton joinButton = new JButton("Join Game");
    private final Component[] onlineComponents;;
    //Immagine decoration
    ImageIcon imageIcon = new ImageIcon( "graphics"+File.separator+"decoration"+File.separator+"BombermanLogo.png");
    JLabel logoLabel = new JLabel(imageIcon);
    //Immagine di sfondo
    ImageIcon backgroundGIF = new ImageIcon("graphics"+File.separator+"decoration"+File.separator+"background.gif");
    JLabel backgroundLabel = new JLabel(backgroundGIF);
    //Font
    Font pixelFont;

    public selectionWindow(){  // ForegroundPanel contiene logoPanel e selectionPanel ed ha un layout a griglia 2x1
        //Caratteristiche e comportamento della frame
        super("BomberMan Game");
        this.setVisible(true);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setResizable(false);
        this.setSize(800, 600);
        //this.setLayout(new FlowLayout());
        // Posiziona la finestra al centro dello schermo
        this.setLocationRelativeTo(null);

        //Background Panel
        backgroundPanel.add(backgroundLabel);
        this.add(backgroundPanel);
        //this.setComponentZOrder(backgroundPanel, 1);

        //Foreground Panel
        foregroundPanel.setLayout(new GridLayout(2,1));
        foregroundPanel.add(logoPanel);
        foregroundPanel.add(selectionPanel);
        this.add(foregroundPanel);
        //this.setComponentZOrder(backgroundPanel, 0);

        //JPanel per la decorazione
        logoPanel.add(logoLabel);

        //JPanel per la selezione
        selectionPanel.setLayout(new GridLayout(1,2));
        selectionPanel.add(offlinePanel);
        selectionPanel.add(onlinePanel);

        //JPanel per la selezione offline
        offlinePanel.setLayout(new BoxLayout(offlinePanel, BoxLayout.Y_AXIS));
        offlinePanel.add(offlineButton);
        offlinePanel.add(offlineButton_twoPlayer);
        offlinePanel.add(offlineButton_threePlayer);
        offlinePanel.add(offlineButton_fourPlayer);
        //Centrare gli elementi nel pannello (perchè il box layout altrimenti li allinea a sinistra)
        offlineButton.setAlignmentX(Component.CENTER_ALIGNMENT);
        offlineButton_twoPlayer.setAlignmentX(Component.CENTER_ALIGNMENT);
        offlineButton_threePlayer.setAlignmentX(Component.CENTER_ALIGNMENT);
        offlineButton_fourPlayer.setAlignmentX(Component.CENTER_ALIGNMENT);
        offlineComponents = offlinePanel.getComponents(); //Lista dei componenti del panello offline (viene poi utilizzata per i listener)

        //JPanel per la selezione online
        onlinePanel.setLayout(new BoxLayout(onlinePanel, BoxLayout.Y_AXIS));
        onlinePanel.add(onlineButton);
        onlinePanel.add(onlineButton_twoPlayer);
        onlinePanel.add(onlineButton_threePlayer);
        onlinePanel.add(onlineButton_fourPlayer);
        onlinePanel.add(joinButton);
        //Centrare gli elementi nel pannello (perchè il box layout altrimenti li allinea a sinistra)
        onlineButton.setAlignmentX(Component.CENTER_ALIGNMENT);
        onlineButton_twoPlayer.setAlignmentX(Component.CENTER_ALIGNMENT);
        onlineButton_threePlayer.setAlignmentX(Component.CENTER_ALIGNMENT);
        onlineButton_fourPlayer.setAlignmentX(Component.CENTER_ALIGNMENT);
        joinButton.setAlignmentX(Component.CENTER_ALIGNMENT);
        onlineComponents = onlinePanel.getComponents(); //Lista dei componenti del panello online (viene poi utilizzata per i listener)

        //Carica il font
        pixelFont = new pixelFont().getPixelFont();

        //Gestione componenti offline
        offlineActionListener offlineAL = new offlineActionListener(offlineComponents,onlineComponents, this); ;
        for (Component component : offlineComponents){
            JButton button = (JButton) component;
            if (button != offlineButton) { //Escludo il bottone offline perchè deve rimanere sempre visibile e attivo
                button.setVisible(false);
                button.setEnabled(false);
            }
            button.setFont(pixelFont);
            button.setContentAreaFilled(false); //Rimuove il background del bottone
            button.setBorderPainted(false); //Rimuove il bordo del bottone
            button.addActionListener(offlineAL);
        }

        //Gestione componenti online
        onlineActionListener onlineAL = new onlineActionListener(onlineComponents,offlineComponents, this); ;
        for (Component component : onlineComponents){
            JButton button = (JButton) component;
            if (button != onlineButton) { //Escludo il bottone online perchè deve rimanere sempre visibile e attivo
                button.setVisible(false);
                button.setEnabled(false);
            }
            button.setFont(pixelFont);
            button.setContentAreaFilled(false); //Rimuove il background del bottone
            button.setBorderPainted(false); //Rimuove il bordo del bottone
            button.addActionListener(onlineAL);
        }
        //Modifica icona della finestra
        this.setIconImage(new ImageIcon("graphics"+File.separator+"decoration"+File.separator+"icon.png").getImage());
    }

    public static void main(String[] args) {
        selectionWindow window = new selectionWindow();
    }
}



I tried to use a JLayeredPane and the method setComponentZOrder but i can't manage to make them work, what am i missing? I'm 100% sure all the addresses are right (if i comment this.add(foregroundPanel) the gif is correctly shown). Thanks for any responses <3

I tried to use a JLayeredPane and the method setComponenetZOrder (in those cases i would also add foregroundPanel.setOpaque(false)), expecting them organize the window in such a way so all the contents of foregroundPanel were visible and the gif would play in the background without overlapping any other components. I tried to implement them in many different ways, sometimes completely changing the structure of the GUI but i always got the same two results: only one of the panels was visible or the backgroundPanel would be above the foregroundPanel and i only could see the buttons for a split second when i hovered my mouse over them.

Thanks for the answers (it's my first question on this platform so i don't really know how to use it), I really appreciate them but there seems to be a missunderstanding. My goal was to combine the contents of backgroundPanel, which should look something like this: [backgroundPanelContent]: (https://i.sstatic.net/1PPV2r3L.gif)
and the contents of foregroundPanel, which should look something like this: [foregroundPanelContent]: (https://i.sstatic.net/Qs66gmdn.png) to make a frame similar to this:[result]: (https://i.sstatic.net/6qY1nVBM.gif) (Sorry for bad photoshop i threw it together in a few minutes)


Solution

  • You can use the GridBagLayout to stack to components on top of one another on the Z axis. The trick is to:

    1. add both components to the same grid
    2. add the components in the reverse order you want them painted

    Simple example:

    import java.awt.*;
    import javax.swing.*;
    
    public class GridBagStack extends JPanel
    {
        public GridBagStack()
        {
            setLayout( new GridBagLayout() );
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 0;
    
            JPanel foreground = new JPanel(new FlowLayout());
            foreground.setOpaque(false);
            foreground.add( new JButton("Button1") );
            foreground.add( new JButton("Button2") );
            add(foreground, gbc);
    
            JLabel background = new JLabel( new ImageIcon("???.jpg") );
            add(background, gbc);
        }
    
        private static void createAndShowUI()
        {
            JFrame frame = new JFrame("GridBagStack");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.add( new GridBagStack() );
            frame.pack();
            frame.setLocationByPlatform( true );
            frame.setVisible( true );
        }
    
        public static void main(String[] args)
        {
            java.awt.EventQueue.invokeLater( () -> createAndShowUI() );
        }
    }