将 java 小程序的图形内容保存到图像文件无法正常工作

Save graphical content of java applet to image file doesn't work properly

我正在尝试将 Java 小程序的图形内容自动保存到图像文件中,但我遇到了文件无法正确保存的问题。我的完整 Java 代码是:

package nl.mark.SierpinskiCarpet;

import java.applet.Applet;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.RenderingHints;
import java.awt.Transparency;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

public class SierpinskiCarpet extends Applet {
    private Graphics g = null;
    private int d0 = 729; // 3^6
    private BufferedImage bufferedImage;
    private final GraphicsConfiguration gConfig = GraphicsEnvironment
            .getLocalGraphicsEnvironment().getDefaultScreenDevice()
            .getDefaultConfiguration();

    public void init() {
        g = getGraphics();
        resize(d0, d0);
    }

    public void paint(Graphics g) {
        drawSierpinskiCarpet(0, 0, getWidth(), getHeight());
        storeImage();
    }

    public void storeImage() {
        BufferedImage image = create(d0, d0, true);
        Graphics2D g = image.createGraphics();
        // you can disable this if you don't want smooth graphics
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
        drawSierpinskiCarpet(0, 0, getWidth(), getHeight());
        g.dispose();
        try {
            ImageIO.write(image, "png", new File(
                    "N:\Tapijt van Sierpiński\image.png"));
        } catch (IOException e) {
        }
    }

    private void drawSierpinskiCarpet(int xOL, int yOL, int breedte, int hoogte) {
        if (breedte > 2 && hoogte > 2) {
            int b = breedte / 3;
            int h = hoogte / 3;
            g.fillRect(xOL + b, yOL + h, b, h);
            for (int k = 0; k < 9; k++)
                if (k != 4) {
                    int i = k / 3;
                    int j = k % 3;
                    drawSierpinskiCarpet(xOL + i * b, yOL + j * h, b, h);
                }
        }
    }

    private BufferedImage create(final int width, final int height,
            final boolean alpha) {
        BufferedImage buffer = gConfig.createCompatibleImage(width, height,
                alpha ? Transparency.TRANSLUCENT : Transparency.OPAQUE);
        return buffer;
    }
}

小程序中显示的图像 (Sierpinski Carpet) 是正确的,但创建的文件只是一张空白图像。要绘制图案,调用方法 drawSierpinskiCarpet() 并在执行函数后调用函数 storeImage() 来保存图像,但会在输出目录中生成空白图像文件。图片保存过程中出现什么问题?

您应该 永远 在组件上调用 getGraphics(并且 永远 存储一个 Graphics 对象作为参数给 paint 左右)。

(而且你永远不应该默默地吞下一个 IOException。至少添加一些 e.printStackTrace() 以知道什么时候出了问题)。

这里的问题是你从图像中获取了Graphics对象,但是对drawSierpinskiCarpet的调用仍然使用了Graphics g,它作为字段存储在class.

在这种情况下,一个简单的解决方案是通过递归调用将 Graphics 对象作为参数传递:

import java.applet.Applet;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.RenderingHints;
import java.awt.Transparency;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

public class SierpinskiCarpet extends Applet
{
    private int d0 = 729; // 3^6
    private BufferedImage bufferedImage;
    private final GraphicsConfiguration gConfig = GraphicsEnvironment
        .getLocalGraphicsEnvironment().getDefaultScreenDevice()
        .getDefaultConfiguration();

    public void init()
    {
        resize(d0, d0);
    }

    public void paint(Graphics g)
    {
        drawSierpinskiCarpet(g, 0, 0, getWidth(), getHeight());
        storeImage();
    }

    public void storeImage()
    {
        BufferedImage image = create(d0, d0, true);
        Graphics2D g = image.createGraphics();
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
        drawSierpinskiCarpet(g, 0, 0, getWidth(), getHeight());
        g.dispose();
        try
        {
            ImageIO.write(image, "png", new File(
                "C:\Users\User\Desktop\sierpinskiImage.png"));
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }

    private void drawSierpinskiCarpet(Graphics g, int xOL, int yOL,
        int breedte, int hoogte)
    {
        if (breedte > 2 && hoogte > 2)
        {
            int b = breedte / 3;
            int h = hoogte / 3;
            g.fillRect(xOL + b, yOL + h, b, h);
            for (int k = 0; k < 9; k++)
                if (k != 4)
                {
                    int i = k / 3;
                    int j = k % 3;
                    drawSierpinskiCarpet(g, xOL + i * b, yOL + j * h, b, h);
                }
        }
    }

    private BufferedImage create(final int width, final int height,
        final boolean alpha)
    {
        BufferedImage buffer =
            gConfig.createCompatibleImage(width, height, alpha
                ? Transparency.TRANSLUCENT : Transparency.OPAQUE);
        return buffer;
    }
}