How to draw an image over another image?
I have a Java project that's about traffic network simulation in a random city, I've managed to figure out a way to implement this project, so I divided each intersection into a section which is basically an extended JPanel class (named Carrefour)...everything works well until I got stuck with how to draw vehicles and make them pass through roads.
So my problem is how to draw an image (vehicle image) over an another image (road)?
Solution 1:
Another approach that does not require extending components.
import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.util.Random;
import java.net.URL;
import javax.imageio.ImageIO;
public class ImageOnImage {
ImageOnImage(final BufferedImage bg, BufferedImage fg) {
final BufferedImage scaled = new BufferedImage(
fg.getWidth()/2,fg.getHeight()/2,BufferedImage.TYPE_INT_RGB);
Graphics g = scaled.getGraphics();
g.drawImage(fg,0,0,scaled.getWidth(),scaled.getHeight(),null);
g.dispose();
final int xMax = bg.getWidth()-scaled.getWidth();
final int yMax = bg.getHeight()-scaled.getHeight();
final JLabel label = new JLabel(new ImageIcon(bg));
ActionListener listener = new ActionListener() {
Random random = new Random();
public void actionPerformed(ActionEvent ae) {
Graphics g = bg.getGraphics();
int x = random.nextInt(xMax);
int y = random.nextInt(yMax);
g.drawImage( scaled, x, y, null );
g.dispose();
label.repaint();
}
};
Timer timer = new Timer(1200, listener);
timer.start();
JOptionPane.showMessageDialog(null, label);
}
public static void main(String[] args) throws Exception {
URL url1 = new URL("http://i.stack.imgur.com/lxthA.jpg");
final BufferedImage image1 = ImageIO.read(url1);
URL url2 = new URL("http://i.stack.imgur.com/OVOg3.jpg");
final BufferedImage image2 = ImageIO.read(url2);
//Create the frame on the event dispatching thread
SwingUtilities.invokeLater(new Runnable(){
@Override
public void run() {
new ImageOnImage(image2, image1);
}
});
}
}
Solution 2:
If this is Swing, then draw the background image in a BufferedImage. Display this BufferedImage in a JComponent's (such as a JPanel's) paintComponent method using Graphic's drawImage(...)
method, and then draw the changing images over this in the same paintComponent method. Don't forget to call the super.paintComponent(...)
method first though.
Please note that this question has been asked quite a bit here and elsewhere, and as you would expect, there are lots of examples of this sort of thing that you can find here with a bit of searching.
Edit
You ask:
Thanks, this is how I draw the firt image (road)
Again, you would create a BufferedImage for this, likely by using ImageIO.read(...)
. Then you'd draw this in your JPanel's paintComponent(Graphics g)
method override using g.drawImage(...)
.
For example...
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.*;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
@SuppressWarnings("serial")
public class IntersectionImagePanel extends JPanel {
private static final String INTERSECTION_LINK = "http://www.weinerlawoffice.com/" +
"accident-diagram.jpg";
private BufferedImage intersectionImage;
public IntersectionImagePanel() {
URL imageUrl;
try {
imageUrl = new URL(INTERSECTION_LINK);
intersectionImage = ImageIO.read(imageUrl );
} catch (MalformedURLException e) {
e.printStackTrace();
System.exit(-1);
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (intersectionImage != null) {
g.drawImage(intersectionImage, 0, 0, this);
}
}
@Override
public Dimension getPreferredSize() {
if (intersectionImage != null) {
int width = intersectionImage.getWidth();
int height = intersectionImage.getHeight();
return new Dimension(width , height );
}
return super.getPreferredSize();
}
private static void createAndShowGui() {
IntersectionImagePanel mainPanel = new IntersectionImagePanel();
JFrame frame = new JFrame("IntersectionImage");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}