-1

I can't get two images to overlap each other in a JFrame. I have tried using one JPanel and two JPanels, and nothing has worked. I have looked into trying out JLayeredPane(s), but to no avail. I have lots of classes that interact so I don't know if showing my code will help, but here is my not-fully-implemented code:

import javax.swing.JLabel;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JLayeredPane;
import javax.swing.ImageIcon;
import java.awt.Graphics2D;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
import java.io.IOException;
import java.awt.event.KeyListener;
import java.awt.event.KeyEvent;

public class MazeDisplay implements KeyListener
{
static JFrame window;
static JPanel backPanel, userPanel;
JLabel user, cpu, maze1, maze2;
User u;

public MazeDisplay(String x, Cell[][] maize1, Cell[][] maize2) throws IOException
{
    maze1 = new JLabel(new ImageIcon(createMazeImage(maize1)));
    maze2 = new JLabel(new ImageIcon(createMazeImage(maize2)));
    user = new JLabel(new ImageIcon("user.png"));
    cpu = new JLabel(new ImageIcon("cpu.png"));
    u = new User(maize1);
    window = new JFrame(x);
    window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    window.setBounds(400, 400, 986, 509);
    backPanel = (JPanel) window.getContentPane();
    backPanel.setLayout(null);
    maze1.setBounds(0, 0, 480, 480);
    maze2.setBounds(500, 0, 480, 480);
    backPanel.add(maze1);
    backPanel.add(maze2);
    userPanel = new JPanel(null);
    user.setBounds(0, 0, 30, 30);
    cpu.setBounds(500, 0, 30, 30);
    userPanel.add(user);
    userPanel.add(cpu);
    window.add(userPanel);
    window.setResizable(false);
    window.setVisible(true);
}

public void keyPressed(KeyEvent e) {}

public void keyReleased(KeyEvent e) {}

public void keyTyped(KeyEvent e) {}

public boolean isLegal(int dir)
{
    boolean ret = false; Cell[][] maze = u.getMaize();
    if(0 <= u.xPos() && u.xPos() < maze.length && 0 <= u.yPos() && u.yPos() < maze.length)
    {
        if(dir == 0) ret = (maze[u.xPos()][u.yPos()].isOpen(dir) && maze[u.xPos()][u.yPos()-1].isOpenO(dir));
        else if(dir == 1) ret = (maze[u.xPos()][u.yPos()].isOpen(dir) && maze[u.xPos()+1][u.yPos()].isOpenO(dir));
        else if(dir == 2) ret = (maze[u.xPos()][u.yPos()].isOpen(dir) && maze[u.xPos()][u.yPos()+1].isOpenO(dir));
        else if(dir == 3) ret = (maze[u.xPos()][u.yPos()].isOpen(dir) && maze[u.xPos()-1][u.yPos()].isOpenO(dir));
    }
    return ret;
}

public static BufferedImage createMazeImage(Cell[][] maze) throws IOException
{
    BufferedImage[][] iMaze = new BufferedImage[maze.length][maze.length];
    for(int i = 0; i < iMaze.length; i++)
        for(int j = 0; j < iMaze.length; j++)
        {
            String cellDir = maze[i][j] + ".png";
            iMaze[i][j] = new BufferedImage(30, 30, BufferedImage.TYPE_INT_RGB);
            Graphics2D icon = iMaze[i][j].createGraphics();
            icon.drawImage(ImageIO.read(new File(cellDir)), 0, 0, null);
        }

    int xOff = 0, yOff = 0;
    BufferedImage mazeImage = new BufferedImage(maze.length * 30, maze.length * 30, BufferedImage.TYPE_INT_RGB);
    Graphics2D g = mazeImage.createGraphics();

    for(int r = 0; r < iMaze.length; r++)
    {
        for(int c = 0; c < iMaze.length; c++)
        {
            g.drawImage(iMaze[r][c], xOff, yOff, null);
            yOff += 30;
        }
        yOff = 0;
        xOff += 30;
    }
    return mazeImage;
}

public static void main(String[] args) throws IOException
{
    MazeGen g = new MazeGen(16);
    MazeGen h = new MazeGen(16);
    MazeDisplay m = new MazeDisplay("Maze Game", g.getMaze(), h.getMaze());
}
}

Edit: My apologies for being so vague, I was extremely tired and irritated at the time. Even though I was vague, the help was very much appreciated, as I got it working using GridBagLayout as MadProgrammer suggested.

androo
  • 3
  • 4
  • 2
    *"I have lots of classes that interact so I don't know if showing my code will help"* 1) For better help sooner, post a [MCVE] or [Short, Self Contained, Correct Example](http://www.sscce.org/). 2) One way to get image(s) for an example is to hot link to images seen in [this Q&A](http://stackoverflow.com/q/19209650/418556). 3) Java GUIs have to work on different OS', screen size, screen resolution etc. using different PLAFs in different locales. As such, they are not conducive to pixel perfect layout. Instead use layout managers, .. – Andrew Thompson May 29 '18 at 02:23
  • .. or [combinations of them](http://stackoverflow.com/a/5630271/418556) along with layout padding and borders for [white space](http://stackoverflow.com/a/17874718/418556). 4) See [Detection/fix for the hanging close bracket of a code block](http://meta.stackexchange.com/q/251795/155831) for a problem I could no longer be bothered fixing. – Andrew Thompson May 29 '18 at 02:23
  • At a glance I cannot see any obvious issues with how you create your labels. Please provide a working example that demonstrates your issue. – sorifiend May 29 '18 at 02:27
  • 2
    BTW - image overlapping can be easily achieved when [custom painting](https://docs.oracle.com/javase/tutorial/uiswing/painting/index.html) a component.. – Andrew Thompson May 29 '18 at 02:36
  • 2
    What do you mean by *overlap*? Are you expecting the tranparency of the `.png` images to be transparent? – karmakaze May 29 '18 at 02:41

2 Answers2

1

So, this is a really quick example.

It makes use of a GridBagLayout to allow two components to occupy the same space at the same time. It then uses a simple Timer to update the location of the player, to demonstrate that the basic concept works.

It's a mea, Mario

import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    JFrame frame = new JFrame();
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        });
    }

    public class TestPane extends JPanel {

        private JLabel player;

        public TestPane() throws IOException {
            BufferedImage tileImg = ImageIO.read(getClass().getResource("Tile.jpg"));
            BufferedImage playerImg = ImageIO.read(getClass().getResource("Mario.png"));
            Icon tileIcon = new ImageIcon(tileImg);
            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            player = new JLabel(new ImageIcon(playerImg));
            gbc.gridx = 0;
            gbc.gridy = 0;
            add(player, gbc);
            for (int row = 0; row < 10; row++) {
                for (int col = 0; col < 10; col++) {
                    gbc.gridx = col;
                    gbc.gridy = row;
                    add(new JLabel(tileIcon), gbc);
                }
            }

            Timer timer = new Timer(500, new ActionListener() {
                private int x = 0;
                private int y = 0;
                @Override
                public void actionPerformed(ActionEvent e) {
                    x++;
                    if (x > 9) {
                        x = 0;
                        y++;
                    }
                    if (y > 9) {
                        y = 0;
                    }
                    GridBagLayout layout = (GridBagLayout) getLayout();
                    GridBagConstraints gbc = layout.getConstraints(player);
                    gbc.gridx = x;
                    gbc.gridy = y;
                    layout.setConstraints(player, gbc);
                    revalidate();
                }
            });
            timer.start();
        }

    }

}

Because of the way that the API works, components are displayed in LIFO order, this means that the player component must be added first.

You could also combine this with a JLayeredPane which would give you control over the z-ordering of the components

Disclaimer...

While this solution does work, it's not very easy to maintain or manage. A better solution would be to follow a custom painting route, this will give you much more control over what is painted and when and where.

Take a look at Performing Custom Painting for some basic details

Community
  • 1
  • 1
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
0

Layered panes should work fine if well-implemented, here is more information about it, how to use it and some examples and codes for it:

https://docs.oracle.com/javase/tutorial/uiswing/components/layeredpane.html

Abdullah
  • 147
  • 2
  • 12
  • Great link, and although using JLayeredPane's will work, it is not necessary. A jLabel is more than capable of doing what OP wants provided that they are added to the JFrame in the correct order. – sorifiend May 29 '18 at 02:32
  • 2
    @sorifiend While you're right, `JLayeredPane` does offer somewhat more obvious z-order handling - just saying ;) – MadProgrammer May 29 '18 at 02:54