We help IT Professionals succeed at work.

Overlapping BufferedImages

mitzdadon
mitzdadon asked
on
Medium Priority
473 Views
Last Modified: 2013-11-23
Hi,

I am trying to create a card game with overlapping cards. Each card is created as a BufferedImage in a class that extends a JPanel (ImagePanel). The ImagePanels are then used inside a JFrame. However, for each ImagePanel that is added to the JFrame, only the last one added appears on the content pane. Am I doing something wrong? I have a feeling its to do with the opacity of the component, but can't seem to figure it out. Any pointers in the right direction will be appreciated. I have added a simplified version of the code I am using to run this.

Thanks,
public class ImagePanel extends JPanel{
	int x,y;
	MainWindow mainWin;
	BufferedImage image;  
 
    public ImagePanel(String p, int x, int y, Color c) throws IOException{
        this.x=x;
        this.y=y;
        mainWin = win;
        String path = "src/images/"+p+".gif";
        image = ImageIO.read(new File(path));
        setSize(image.getWidth(), image.getHeight());
    }
 
    protected void paintComponent(Graphics g){
        super.paintComponent(g);
 
		g.drawImage(image, x, y, mainWin);
    }
 
}
 
public class MainWindow extends JFrame{
    
    ImagePanel img1,img2,img3 ;
    String cardPaths1,cardPaths2,cardPaths3 ;
 
	int x1 = 100;
	int y1 = 100;
	int x2 = 120;
	int y2 = 120;
	int x3 = 140;
	int y3 = 140;
 
 
    public MainWindow(){
		Dimension dimInitScreenSize = Toolkit.getDefaultToolkit().getScreenSize() ;
        int wndWidth = dimInitScreenSize.width*2/3 ;
        int wndHeight = dimInitScreenSize.height*2/3 ;
        setSize( wndWidth , wndHeight ) ;
 
        try {
            img1 = new ImagePanel(this, "a.gif",x1,y1,Color.green);
            img2 = new ImagePanel(this, "b.gif",x2,y2,Color.blue);
            img3 = new ImagePanel(this, "c.gif",x3,y3,Color.red);
        } catch (IOException ex) {
            Logger.getLogger(MainWindow.class.getName()).log(Level.SEVERE, null, ex);
        }
 
        getContentPane().add(img1);
        getContentPane().add(img2);
        getContentPane().add(img3);
 
        setVisible(true);
    }
}

Open in new window

Comment
Watch Question

ksivananthVice President

Commented:
because you laying the panels on top of one another,

        getContentPane().add(img1);
        getContentPane().add(img2);
        getContentPane().add(img3);

how do you want to displayit?
CERTIFIED EXPERT
Top Expert 2016

Commented:
Set a FlowLayout on your content pane of your frame
CERTIFIED EXPERT
Top Expert 2016

Commented:
e.g.
getContentPane().setLayout(new FlowLayout());
getContentPane().add(img1);
getContentPane().add(img2);
getContentPane().add(img3);

Open in new window

Author

Commented:
The cards should overlap each other, according to the x,y value. For clarity, I am attaching all the files required to run this code, and a screenshot of the output. If you create a main class/method and run, you should see the problem I am facing.

From here, you will notice that 2 of the cards are not being displayed at all, so setting a FlowLayout wont help.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JFrame;import javax.swing.JPanel;
;
 
public class MainWindow extends JFrame{
    
    ImagePanel img1,img2,img3 ;
    String cardPaths1,cardPaths2,cardPaths3 ;
    Rectangle imgFrame1,imgFrame2,imgFrame3;
 
    int x1 = 100;
    int y1 = 100;
    int x2 = 120;
    int y2 = 120;
    int x3 = 140;
    int y3 = 140;
    
    public MainWindow(){
		Dimension dimInitScreenSize = Toolkit.getDefaultToolkit().getScreenSize() ;
        int wndWidth = dimInitScreenSize.width*2/3 ;
        int wndHeight = dimInitScreenSize.height*2/3 ;
        setSize( wndWidth , wndHeight ) ;
 
        cardPaths1 = new String("5h");
        cardPaths2 = new String("2c");
        cardPaths3 = new String("8d");
        try {
            img1 = new ImagePanel(this, cardPaths1,x1,y1,Color.green);
            img2 = new ImagePanel(this, cardPaths2,x2,y2,Color.blue);
            img3 = new ImagePanel(this, cardPaths3,x3,y3,Color.red);
        } catch (IOException ex) {
            Logger.getLogger(MainWindow.class.getName()).log(Level.SEVERE, null, ex);
        }
 
        img1.setLocation(x1,y1);
        getContentPane().add(img1);
        img2.setLocation(x2,y2);
        getContentPane().add(img2);
        img3.setLocation(x3,y3);
        getContentPane().add(img3);
 
        setVisible(true);
    }
}
 
class ImagePanel extends JPanel{
    BufferedImage image;
    int x,y;
    MainWindow mainWin;
 
    public ImagePanel(MainWindow win, String p, int x, int y, Color c) throws IOException{
        this.x=x;
        this.y=y;
        mainWin = win;
        String path;
        path = "src/images/" + p + ".gif";
        image = ImageIO.read(new File(path));
 
        setSize(image.getWidth(), image.getHeight());
        setBackground(c);
    }
 
    protected void paintComponent(Graphics g){
        super.paintComponent(g);
        g.drawImage(image, x, y, mainWin);
    }
}

Open in new window

5h.gif
2c.gif
8d.gif
output.gif
ksivananthVice President

Commented:
set opaque false to all panels!
ksivananthVice President

Commented:
like this,

public ImagePanel(String p, int x, int y, Color c) throws IOException{
        this.x=x;
        this.y=y;
        mainWin = win;
        String path = "src/images/"+p+".gif";
        image = ImageIO.read(new File(path));
        setOpaque(false) ;
        setSize(image.getWidth(), image.getHeight());
    }

Author

Commented:
I have done that as well ksivananth, but this causes only the last card (8d) to be displayed. The otehrs cant be seen at all!
CERTIFIED EXPERT
Top Expert 2016

Commented:
To get absolute placement of components (not images) like that you should probably use a null layout and place them by coordinates
CERTIFIED EXPERT
Top Expert 2016

Commented:
You also need to change the image coords:
g.drawImage(image, 0, 0, mainWin);

Open in new window

Author

Commented:
Hi CEHJ. As you can see, thats what I have done in teh second set of code that I posted.
        img1.setLocation(x1,y1);
        getContentPane().add(img1);
        img2.setLocation(x2,y2);
        getContentPane().add(img2);
        img3.setLocation(x3,y3);
        getContentPane().add(img3);
 

Author

Commented:
CEHJ. That has improved things. It now makes all the cards appear, but the last one that was added (8d) is drawn as (0,0), whereas the others 2 are drawn as specified by teh x,y values.

Author

Commented:
Here is a screenshot..
output.gif
CERTIFIED EXPERT
Top Expert 2016

Commented:
This is my screen after implementing my own advice:
cards.png

Author

Commented:
Thats strange...not sure why I don't get the same as you. Did you change the layout as well, or only the co-ordinates of the image?
CERTIFIED EXPERT
Top Expert 2016
Commented:
(Don't forget to set the null layout)

Not the solution you were looking for? Getting a personalized solution is easy.

Ask the Experts
CERTIFIED EXPERT
Top Expert 2016

Commented:
:-)

Author

Commented:
Sorry...forget to add my comments!

Thanks very much CEHJ. I didnt realise the impact of setting teh layout to null on this scenario. It never even crossed my mind. The naswer you provided was spot on.

thanks again.
Access more of Experts Exchange with a free account
Thanks for using Experts Exchange.

Create a free account to continue.

Limited access with a free account allows you to:

  • View three pieces of content (articles, solutions, posts, and videos)
  • Ask the experts questions (counted toward content limit)
  • Customize your dashboard and profile

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.