Java将2D图形作为参数传递

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

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

我有一个function绘制,它在gui屏幕上创建图像和另一个保存它的function保存到磁盘,但保存function也调用绘图。

是否可以保存已经绘制的图像而无需重新调用绘图function,因为它在我的代码中完成?

我正在回答你关于显示到GUI和使用单个对象/变量保存到磁盘的问题,但它可能由于您的问题的类似性质而关闭。 我认为有几个问题你似乎很困惑,我想在这里编写我的解决方案,这也解决了你的重复post中的问题。


是否可以保存已经绘制的图像而无需重新调用绘图function,因为它在我的代码中完成?

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

 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)包含任何其他代码。 不要实现将代码保存到此处文件的代码。

  • 尽量不要在paintComponent(Graphics)创建新的BufferedImage。 如果没有,将在每次重绘时创建一个新的BufferedImage实例。

更改创建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); } } } 

编辑

我在另一篇文章中找到了答案。 绘图两次并不是一个坏主意。 你正在做的是像@Hovercraft在这篇文章中所说的那样,将屏幕绘图与写入文件分开,这样你就不会看到你的图形绘制性能受到伤害。

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