绘画不保存到缓冲图像

paint not saving to bufferedimage

当我在 paintComponent() 中包含所有绘图代码时,下面的代码正确地将图表绘制到 JPanel。但是我想将结果保存到硬盘上的图像文件中以供其他地方使用。因此,我将绘图代码移动到 updatePaint() 方法中,并采取了下面显示的其他步骤首先绘制到 bufferedimage,然后让 bufferedimage 可用于打印到 JPanel 和到保存的文件。问题是下面的代码只打印了一个黑色 JPanel 而不是我重新排列代码之前正在绘制的图表。

如何更改下面的代码,以便缓冲图像显示预期的图表,并正确绘制到 JPanel,而不影响其保存到文件的能力?

package somepackage;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class ChartPanel extends JPanel {
    private BufferedImage paintImage = new BufferedImage(500, 400, BufferedImage.TYPE_3BYTE_BGR);

    private double[] values;
    private String[] names;
    private String title;
    private double fac_result;

    public ChartPanel(double[] v, String[] n, String t, double fac_res) {
        names = n;
        values = v;
        title = t;
        fac_result = fac_res;
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawImage(paintImage, 0, 0, null);
    }

    // draw painting
    public void updatePaint(){
        Graphics g = paintImage.createGraphics();

        // draw on paintImage using Graphics
        if (values == null || values.length == 0)
            return;
        double minValue = 0;
        double maxValue = 0;
        for (int i = 0; i < values.length; i++) {
            if (minValue > values[i])
                minValue = values[i];
            if (maxValue < values[i])
                maxValue = values[i];
        }

        Dimension d = getSize();
        int clientWidth = d.width;
        int clientHeight = d.height;
        int barWidth = clientWidth / values.length;

        Font titleFont = new Font("SansSerif", Font.BOLD, 20);
        FontMetrics titleFontMetrics = g.getFontMetrics(titleFont);
        Font labelFont = new Font("SansSerif", Font.PLAIN, 10);
        FontMetrics labelFontMetrics = g.getFontMetrics(labelFont);
        int titleWidth = titleFontMetrics.stringWidth(title);
        int y = titleFontMetrics.getAscent();
        int x = (clientWidth - titleWidth) / 2;
        g.setFont(titleFont);
        g.drawString(title, x, y);

        int top = titleFontMetrics.getHeight();
        int bottom = labelFontMetrics.getHeight();
        if (maxValue == minValue)
            return;
        double scale = (clientHeight - top - bottom) / (maxValue - minValue);
        y = clientHeight - labelFontMetrics.getDescent();
        g.setFont(labelFont);
System.out.println("fac_result in paintComponent() is: "+fac_result);
    for (int i = 0; i < values.length; i++) {
        int valueX = i * barWidth + 1;
        int valueY = top;
        int height = (int) (values[i] * scale);
    if (values[i] >= 0)
        valueY += (int) ((maxValue - values[i]) * scale);
    else {
        valueY += (int) (maxValue * scale);
        height = -height;
    }
System.out.println("names["+i+"] is: "+names[i]);
    if((Double.parseDouble(names[i])<=(fac_result+0.5))&&(Double.parseDouble(names[i])>=(fac_result-0.5))){
        g.setColor(Color.cyan);
        g.fillRect(valueX, valueY, barWidth - 2, height);
        System.out.println("condition met.");
    }
    else{
        g.setColor(Color.red);
        g.fillRect(valueX, valueY, barWidth - 2, height);
    }
    g.setColor(Color.black);
    g.drawRect(valueX, valueY, barWidth - 2, height);
    if(i%5==0){
        int labelWidth = labelFontMetrics.stringWidth(names[i]);
        x = i * barWidth + (barWidth - labelWidth) / 2;
        g.drawString(names[i], x, y);
    }
    }
///////////     
    g.dispose();
    // repaint panel with new modified paint
    repaint();
}

public void save() throws IOException{
    ImageIO.write(paintImage, "PNG", new File("C:\Temp\filename.png"));
}

public void load() throws IOException {
    paintImage = ImageIO.read(new File("C:\Temp\filename.png"));
    // update panel with new paint image
    repaint();
}

}

注意:以上代码是从另一个 class 使用以下行调用的:

new ChartPanel(values, names, label, fac_result));
  1. 要更新 BufferedImage 的状态,您可以检查 paintImage 是否为 null 并在调用 paintComponent 时创建和呈现它。
  2. 就像任何绘画一样,您必须在绘画之前清除 Graphics 上下文。凭记忆,将颜色设置为透明色,并在绘制之前使用clearRect将内容清除回透明状态。