I am trying to draw on a buffered image. I am able to get the picture on the frame but it doesnt seem to draw on the image. If I use
BufferedImage bufferedImage = new BufferedImage(1280, 800,BufferedImage.TYPE_INT_RGB);
then it seems to draw the string but I would like to ideally draw on the image as I need to plot some coordinates on the image for a project. Any guidance would be highly appreciated. Excuse the bad indentation
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class drawTest extends JPanel {
public void paint(Graphics g) {
Image img = createImageWithText();
g.drawImage(img, 20,20,this);
}
private Image createImageWithText(){
BufferedImage bufferedImage = new BufferedImage(1280, 800,BufferedImage.TYPE_INT_RGB);
// BufferedImage bufferedImage = new BufferedImage()
Graphics g = bufferedImage.getGraphics();
try {
bufferedImage = ImageIO.read(getClass().getResource("Unknown.jpg"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
g.drawString("Point is here", 20,20);
return bufferedImage;
}
public static void main(String[] args) {
JFrame frame = new JFrame();
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
double width = screenSize.getWidth();
double height = screenSize.getHeight();
frame.getContentPane().add(new drawTest());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// frame.setSize(200, 200);
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
System.out.println(height + " " + width);
frame.setVisible(true);
}
}
You're creating two BufferedImage objects -- one that you get the Graphics context from and draw text on, and the other that holds the picture obtained via ImageIO, that you don't draw text on. You return the latter, so it makes sense that the picture holds no new text.
// BufferedImage Object ONE
BufferedImage bufferedImage = new BufferedImage(1280, 800, BufferedImage.TYPE_INT_RGB);
Graphics g = bufferedImage.getGraphics(); // Graphics for the first object only
try {
// BufferedImage object TWO
bufferedImage = ImageIO.read(getClass().getResource("Unknown.jpg"));
} catch (IOException e) {
e.printStackTrace();
}
// draw with the graphics context for the first object
g.drawString("Point is here", 20, 20);
return bufferedImage; // but return the second
Solution: don't do this, create one BufferedImage only, say via ImageIO, get its Graphics context, draw with it, dispose the Graphics when done, and return it.
e.g.,
// have method accept the image path and
// have it throw an exception if the path is bad
private Image createImageWithText2(String resourcePath) throws IOException {
// create one and only one BufferedImage object.
// If this fails, the exception will bubble up the call chain
BufferedImage bufferedImage = ImageIO.read(getClass().getResource(resourcePath));
// get the Graphics context for this single BufferedImage object
Graphics g = bufferedImage.getGraphics();
g.drawString("Point is here", 20, 20);
g.dispose(); // get rid of the Graphics context to save resources
return bufferedImage;
}
Other problems with your code is here:
public void paint(Graphics g) {
Image img = createImageWithText();
g.drawImage(img, 20,20,this);
}
Problems include:
- You're overriding the wrong painting method. You should override paintComponent, not paint, and in fact your question mentions paintComponent, so I'm not sure why you're doing this.
- You're overriding a painting method but not calling the super's method, breaking the painting chain.
- You're doing file I/O unnecessarily repeatedly within a painting method, a method that has the greatest effect on the perceived responsiveness of your GUI, and so something you don't want to do. Read the image in once store it to a variable, use the variable within paintComponent, and never do file I/O within a painting method.
- You will want to learn and use Java naming conventions. Variable names should all begin with a lower letter while class names with an upper case letter. Learning this and following this will allow us to better understand your code, and would allow you to better understand the code of others.