在缓冲图像上绘图

我正在尝试在缓冲图像上绘图.我能够在框架上获得图片,但它似乎没有在图像上绘制.如果我使用

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);
 }
}

推荐答案

您正在创建 两个 BufferedImage 对象 - 一个从中获取 Graphics 上下文并在其上绘制文本,另一个用于保存通过 ImageIO 获得的图片,您不要在其上绘制文本.您返回后者,因此图片不包含新文本是有道理的.

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

解决方案:不要这样做,仅创建 一个 BufferedImage,例如通过 ImageIO,获取其 Graphics 上下文,使用它进行绘制,完成后处置 Graphics,然后退货.

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.

例如,

// 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);
}

问题包括:

  • 您覆盖了错误的绘制方法.您应该覆盖paintComponent,而不是paint,实际上您的问题提到了paintComponent,所以我不确定您为什么要这样做.
  • 你重写了一个绘画方法,但没有调用 super 的方法,破坏了绘画链.
  • 您在绘画方法中不必要地重复执行文件 I/O,这种方法对您的 GUI 的感知响应能力影响最大,因此您不想这样做.读取一次中的图像,将其存储到变量中,在paintComponent 中使用该变量,并且永远不要在绘制方法中进行文件I/O.
  • 您将希望学习和使用 Java 命名约定.变量名应全部以小写字母开头,而类名应以大写字母开头.学习并遵循这一点将使我们能够更好地理解您的代码,并使您能够更好地理解他人的代码.
  • 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.

相关文章