Java 将二维图形作为参数传递

Java Passing 2D Graphic as a Parameter

我有一个绘制图像然后立即保存的功能,但问题是它似乎绘制了两次,一次用于屏幕上的视图,一次用于将其保存到磁盘

public class myFrame {

    public static void main(String[] args) {

        JFrame lv_frame = new JFrame();
        // setup jframe here

        lv_frame.add(new image());

        lv_frame.setVisible(true);

    }

}

class image extends JPanel {

    public void paintComponent(Graphics graphic) {

        super.paintComponent(graphic);
        draw(graphic);
        save();

    }

    public void draw(Graphics graphic) {

        Graphics2D graphic2D = (Graphics2D) graphic;
        graphic2D.fillArc(0, 0, 250, 250, 0, 90);

    }

    public void save() {

        BufferedImage image = new BufferedImage(250, 250, BufferedImage.TYPE_4BYTE_ABGR_PRE);
        Graphics2D graphic2D = image.createGraphics();

        try {
            File output = new File("file.png");

            // is it possible to use the graphic I've already
            // drawn here instead of re-drawing?
            draw(graphic2D);

            ImageIO.write(image, "png", output);
        } catch(IOException log) {
            System.out.println(log);
        }

    }

}

我有一个函数 draw 可以在 gui 屏幕上创建图像,另一个函数 save 可以将图像保存到磁盘,但是 save 函数也在调用 draw。

是否可以保存已经绘制的图像,而无需像我的代码中那样重新调用绘制函数?

更改创建 graphics2D 对象的位置并重新使用它。

试试这个。

public class myFrame {

    public static void main(String[] args) {

        JFrame lv_frame = new JFrame();
        // setup jframe here

        lv_frame.add(new image());

        lv_frame.setVisible(true);

    }

}

class image extends JPanel {

    public void paintComponent(Graphics graphic) {

        super.paintComponent(graphic);

        // Image and graphics are now created here
        BufferedImage image = new BufferedImage(250, 250, BufferedImage.TYPE_4BYTE_ABGR_PRE);
        Graphics2D graphic2D = image.createGraphics();

        draw(graphic2D);
        save(image);
    }

    public void draw(Graphics graphic) {

        Graphics2D graphic2D = (Graphics2D) graphic;
        graphic2D.fillArc(0, 0, 250, 250, 0, 90);

    }

    public void save(BufferedImage image) {
        try {
            File output = new File("file.png");
            ImageIO.write(image, "png", output);
        } catch(IOException log) {
            System.out.println(log);
        }

    }

}


编辑

我在另一个 post 中找到了答案。画两次也不错。你正在做的是,就像@Hovercraft 在 中所说的那样,将屏幕绘图与写入文件分开,这样你就不会看到你的图形绘图性能受到损害。

我试过只画过一次,但是你没有简单的方法来存储绘图的 Graphics 对象。可能是为了防止这种情况而实施的。如果您了解该方法的工作方式,您将获得 Graphics 对象,其唯一目的是在其上进行绘制。以其他方式使用它可能会影响性能。

我在 Display to GUI and Save to Disk with a Single Object/Variable 上回答了您的问题,但可能由于您的问题性质相似而被关闭。 我认为您似乎对几个问题感到困惑,我想在这里写下我的解决方案,它也解决了您重复的 post.

中的问题

Is it possible to save the image that has already been drawn without re-calling the draw function as it is being done in my code?

不要混淆在面板上绘制图像和保存图像。以下显示了保存绘制图像的工作示例。

class DrawingSpace extends JPanel
{
    private BufferedImage buf;

    public DrawingSpace(){
        setPreferredSize(new Dimension(200, 200));
        buf = new BufferedImage(200, 200, BufferedImage.TYPE_INT_ARGB);
        drawOnBuffer();
    }

    public void drawOnBuffer(){
        Graphics g = buf.createGraphics();
        g.setColor(Color.BLUE);
        g.fillOval(0,0,200,200);
        g.setColor(Color.RED);
        g.fillOval(50,50,100,100);
        g.dispose();
    }

    public void saveBufferAsImage(String pathname){
        String fmt = "";
        if(!(pathname == null || pathname.equals(""))){
            fmt = pathname.substring(pathname.lastIndexOf(".")+1);
            File outputfile = new File(pathname);
            try{
                ImageIO.write(buf, fmt, outputfile);        
            }catch(IOException ioe){System.out.println("Unable to save file");}
        }       
    }

    @Override
    public void paintComponent(Graphics g){
        super.paintComponent(g);
        g.drawImage(buf, 0, 0, 200, 200, null); //Only for user to see
    }
}

要保存图像,您不一定必须先在 JPanel 中绘制和显示它。请注意,我创建了一个名为 bufBufferedImage,并且我在 buf 上绘图。在 BufferedImage 上绘制后,我可以将该图像简单地保存为文件(我不必先将其绘制到面板上)。

请注意,我执行了以下操作:

    @Override
    public void paintComponent(Graphics g){
        super.paintComponent(g);
        g.drawImage(buf, 0, 0, 200, 200, null); //Only for user to see
    }

g.drawImage(buf, 0, 0, 200, 200, null) 会将 buf 上的任何内容绘制到 JPanel 上。可以删除,保存仍然有效。我在面板上画的时候,只是让用户看到画的结果。

测试程序:

class SaveImageRunner{
    public static void main(String[] args){
        SwingUtilities.invokeLater(new Runnable(){
            @Override
            public void run(){
                JFrame frame = new JFrame("Saving a buffered image");
                DrawingSpace ds = new DrawingSpace();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(ds);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
                ds.saveBufferAsImage("BlueCircle.png");
            }           
        });
    }
}

保存的图片:


绘图上的一些提示:

  • paintComponent(Graphics) 只包含绘图代码,不包含任何其他代码。不要在此处实现将图像保存到文件的代码。

  • 尽量不要在paintComponent(Graphics)中新建BufferedImage。否则,每次重绘时都会创建一个 BufferedImage 的新实例。