1

By using Java swing, what available approach are there to create a foreground image (such as an image of a knight) which is movable on a static background image?

Shall we use JLabel with image icons?

user3437460
  • 17,253
  • 15
  • 58
  • 106
  • Start by taking a look at [Painting in AWT and Swing](http://www.oracle.com/technetwork/java/painting-140037.html) and [Performing Custom Painting](http://docs.oracle.com/javase/tutorial/uiswing/painting/) and [2D Graphics](http://docs.oracle.com/javase/tutorial/2d/) and [How to Use Key Bindings](http://docs.oracle.com/javase/tutorial/uiswing/misc/keybinding.html) and [How to use Swing Timers](http://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html) – MadProgrammer Feb 29 '16 at 23:54

1 Answers1

3

This solution also addresses the issues mentioned in: Images In JFrame are overwriting each other not displaying both images over eachother


If we try to add a background and some foreground images, it can be a little tricky if we intend to let those images overlap each other as many layouts provided by Java may prevent components (such as JLabels) from overlapping each other. Positioning the images to the exact location can be an issue too.

I will suggest a different approach when we want to create a screen similar to those we see in games:

enter image description here

Instead of creating multiple JLabel filled with imageIcon, an alternative will be drawing directly on the panel. This is a customized panel with instances of images we are interested to draw.

class DrawingSpace extends JPanel
{
    private BufferedImage bg, hero;
    private int bgWidth, bgHeight;
    private int heroWidth, heroHeight;  
    private int scWidth, scHeight;
    private int mouseX, mouseY;

    public DrawingSpace(){      
        loadImages();
        init();     
        setPreferredSize(new Dimension(scWidth, scHeight));     
        addMouseMotionListener(new MouseHandler());     
    }

    private void init(){
        mouseX = 0;
        mouseY = 0;
        heroWidth = hero.getWidth();
        heroHeight = hero.getHeight();      
        bgWidth = bg.getWidth();
        bgHeight = bg.getHeight();      
        scWidth = bgWidth;
        scHeight = bgHeight;        
    }

    private void loadImages(){
        try{
            bg = ImageIO.read(getClass().getResource("Images/background.jpg"));
            hero = ImageIO.read(getClass().getResource("Images/knight.png"));
        }catch(IOException ioe){System.out.println("Unable to open file");}
    }

    @Override public void paintComponent(Graphics g){
        super.paintComponent(g);        
        g.drawImage(bg, 0, 0, bgWidth, bgHeight, null);
        g.drawImage(hero, mouseX-(heroWidth/2), mouseY-(heroHeight/2), heroWidth, heroHeight, null);        
    }

    private class MouseHandler implements MouseMotionListener
    {
        @Override public void mouseMoved(MouseEvent e){
            mouseX = e.getX();
            mouseY = e.getY();
            repaint();
        }
        @Override public void mouseDragged(MouseEvent e){}  
    }
}

A runner class to drive the codes:

class KnightRunner
{   
    public static void main(String[] args){

        SwingUtilities.invokeLater(new Runnable(){
            @Override
            public void run(){
                JFrame frame = new JFrame("Knight Runner");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);       
                frame.add(new DrawingSpace());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);             
            }
        });
    }       
}
Community
  • 1
  • 1
user3437460
  • 17,253
  • 15
  • 58
  • 106
  • 1
    `hero = ImageIO.read(getClass().getResource("Images/knight.png"));` 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). Particularly relevant here given it includes a tileset for chess pieces (though your knight is way cool). Another tip on making it an MCVE is to drop the `main` method into the end of the `DrawingSpace` panel. But plus one for the (question &) answer.. :) – Andrew Thompson Feb 29 '16 at 23:36
  • @AndrewThompson Thanks a lot for the encouragement :) – user3437460 Feb 29 '16 at 23:37
  • [Images In JFrame are overwriting each other not displaying both images over eachother](http://stackoverflow.com/questions/35710453/images-in-jframe-are-overwriting-each-other-not-displaying-both-images-over-each?noredirect=1#comment59099957_35710453) would suggest another "possible" solution, but as you can see, there are other options available which might better meet the requirements of that answer – MadProgrammer Feb 29 '16 at 23:56
  • You might consider also having a look at [Java KeyListener vs Keybinding](http://stackoverflow.com/questions/23486827/java-keylistener-vs-keybinding/23486873#23486873) and as a general rule of thumb, prefer key bindings over `KeyListener` – MadProgrammer Feb 29 '16 at 23:57