4

I have a class that uses a CardLayout which has two cards that have a button on them. What I would like to be able to do is put an image that would act like a background such as a desktop background in Windows. The program eventually will have several different cards and I'd like to be able to put different backgrounds on each card. I've tried many suggestions posed in other similar questions on this site as well as whatever I can find through googling it, but I just can't seem to get it to work. I understand that with the CardLayout I can't put a panel on top of a panel, so putting an image on a JPanel wouldn't work. So my question is, based off the code posted below, is there a better way for me to setup my layout so that it works better, and also, how should I approach displaying the image so that it is in the background of the buttons? Any help would be greatly appreciated.

import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.*;

public class Cards implements ActionListener {    
private JPanel cards;
private JButton button1;
private JButton button2;
private Image backgroundImage;

public void addComponentToPane(Container pane) throws IOException {
    backgroundImage = ImageIO.read(new File("background.jpg"));

    //create cards
    JPanel card1 = new JPanel()
    {
        @Override
        public void paintComponent(Graphics g)
        {
            g.drawImage(backgroundImage, 0, 0, null);
        }
    };
    JPanel card2 = new JPanel();
    button1 = new JButton("Button 1");
    button2 = new JButton("Button 2");
    button1.addActionListener(this);
    button2.addActionListener(this);        
    card1.add(button1);        
    card2.add(button2);
    //create panel that contains cards
    cards = new JPanel(new CardLayout());
    cards.add(card1, "Card 1");
    cards.add(card2, "Card 2");
    pane.add(cards, BorderLayout.SOUTH);        
}

public void itemStateChanged(ItemEvent evt) {
    CardLayout cl = (CardLayout)(cards.getLayout());
    cl.show(cards, (String)evt.getItem());
}

public static void createAndShowGUI() throws IOException {
    //create and setup window
    JFrame frame = new JFrame("Frame"); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);        
    //create and setup content pane
    Cards main = new Cards();
    main.addComponentToPane(frame.getContentPane());        
    //display window
    frame.pack();
    frame.setSize(800, 600);
    frame.setResizable(false);
    frame.setVisible(true);
}

public void actionPerformed(ActionEvent ae) {
    if (ae.getSource() == button1) {
        CardLayout cl = (CardLayout) (cards.getLayout());
        cl.show(cards, "Card 2");     
    } else if (ae.getSource() == button2) {
        CardLayout cl = (CardLayout) (cards.getLayout());
        cl.show(cards, "Card 1");
    }        
}            

public static void main(String[] args) {
    //set look and feel
    try {
        UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
    } catch (UnsupportedLookAndFeelException ex) {
        ex.printStackTrace();
    } catch (IllegalAccessException ex) {
        ex.printStackTrace();
    } catch (InstantiationException ex) {
        ex.printStackTrace();
    } catch (ClassNotFoundException ex) {
        ex.printStackTrace();
    }                

    //schedule job for the event dispatch thread creating and showing GUI        
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
        public void run() {                
                try {
                    createAndShowGUI();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

        }
    });     
}   
}
mKorbel
  • 109,525
  • 20
  • 134
  • 319
Jarod
  • 157
  • 2
  • 4
  • 12
  • Please have a look at this [example](http://stackoverflow.com/a/11372350/1057230), it can give you some idea about the directory structure of your project, and also this example, [HOW TO LOAD IMAGES TO JAVA PROJECT](http://stackoverflow.com/a/9866659/1057230) – nIcE cOw Jul 16 '12 at 02:34

2 Answers2

6

You need to override the method paintComponent(Graphics g) of JPanel and use drawImage() on the Graphics object g as in this example.


Also, check these two examples by @trashgod:

  1. example.
  2. example.
Community
  • 1
  • 1
Eng.Fouad
  • 115,165
  • 71
  • 313
  • 417
  • Would I do that to each card, such as the JPanel for card1 and card2 or for the cards JPanel? – Jarod Jul 16 '12 at 00:14
  • 1
    @Jarod Override the JPanel's paintComonent for each card. – Eng.Fouad Jul 16 '12 at 00:16
  • I've updated my code above and I'm getting an error: javax.imageio.IIOException: Can't read input file! Might you be able to give any advice on that? – Jarod Jul 16 '12 at 00:33
  • +1 for citing such nice examples. :-) @Jarod: For two panels, Eng.Fouad's advice is effective. For more, you might consider creating a `MyImagePanel` subclass of `JPanel` that you can use for each of your cards, as suggested [here](http://stackoverflow.com/a/4054307/230513). – trashgod Jul 16 '12 at 00:36
  • 1
    @Jarod: You might verify the name and location; once I got i spelled right, you code worked. The layout will need some attention. – trashgod Jul 16 '12 at 00:46
  • @trashgod I was able to get it working (well, with layout issues as you mentioned) by typing in the full directory, C:\\... is that the normal way to do it or should I be able to do it by simply pointing to "background.jpg" if the file is in the same folder as Cards.java? – Jarod Jul 16 '12 at 00:50
  • @Jarod: More [here](http://stackoverflow.com/a/11496993/230513) on preferred size and resources. – trashgod Jul 16 '12 at 00:59
6

@Eng.Fouad's answer is well chosen, but the image probably dominates the layout. You might want to override getPreferredSize() as shown below. Then you can just pack() the window, and the size will be right. See also Loading Images Using getResource.

import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.*;

public class Cards implements ActionListener {

    private JPanel cards;
    private JButton button1;
    private JButton button2;
    private Image backgroundImage;

    public void addComponentToPane(Container pane) {
        try {
            backgroundImage = ImageIO.read(new File("background.jpg"));
        } catch (IOException ex) {
            ex.printStackTrace(System.err);
        }
        //create cards
        JPanel card1 = new JPanel() {

            @Override
            public void paintComponent(Graphics g) {
                super.paintComponent(g);
                g.drawImage(backgroundImage, 0, 0, null);
            }

            @Override
            public Dimension getPreferredSize() {
                return new Dimension(
                    backgroundImage.getWidth(null),
                    backgroundImage.getHeight(null));
            }
        };
        JPanel card2 = new JPanel();
        button1 = new JButton("Button 1");
        button2 = new JButton("Button 2");
        button1.addActionListener(this);
        button2.addActionListener(this);
        card1.add(button1);
        card2.add(button2);
        //create panel that contains cards
        cards = new JPanel(new CardLayout());
        cards.add(card1, "Card 1");
        cards.add(card2, "Card 2");
        pane.add(cards, BorderLayout.SOUTH);
    }

    public void itemStateChanged(ItemEvent evt) {
        CardLayout cl = (CardLayout) (cards.getLayout());
        cl.show(cards, (String) evt.getItem());
    }

    public static void createAndShowGUI() {
        //create and setup window
        JFrame frame = new JFrame("Frame");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //create and setup content pane
        Cards main = new Cards();
        main.addComponentToPane(frame.getContentPane());
        //display window
        frame.pack();
        frame.setVisible(true);
    }

    public void actionPerformed(ActionEvent ae) {
        if (ae.getSource() == button1) {
            CardLayout cl = (CardLayout) (cards.getLayout());
            cl.show(cards, "Card 2");
        } else if (ae.getSource() == button2) {
            CardLayout cl = (CardLayout) (cards.getLayout());
            cl.show(cards, "Card 1");
        }
    }

    public static void main(String[] args) {
        //schedule job for the event dispatch thread creating and showing GUI        
        EventQueue.invokeLater(new Runnable() {

            public void run() {
                    createAndShowGUI();
            }
        });
    }
}
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • Re-factoring as [`MyImagePanel`](http://stackoverflow.com/a/4054307/230513) left as an exercise. :-) – trashgod Jul 16 '12 at 01:01