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 中绘制和显示它。请注意,我创建了一个名为 buf
的 BufferedImage
,并且我在 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 的新实例。
我有一个绘制图像然后立即保存的功能,但问题是它似乎绘制了两次,一次用于屏幕上的视图,一次用于将其保存到磁盘
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 中绘制和显示它。请注意,我创建了一个名为 buf
的 BufferedImage
,并且我在 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 的新实例。