Java Passing 2D Graphic as a Parameter

前端 未结 2 825
無奈伤痛
無奈伤痛 2021-01-27 09:02

I have a function that is drawing an image and then saving it immediately after but the problem is that it seems to be drawing it twice, once for the view on the screen and then

相关标签:
2条回答
  • 2021-01-27 09:42

    Change the place where you create the graphics2D object and reuse it.

    Try this out.

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


    EDIT

    I have found the answer in another post. It is not a bad idea to make the drawing twice. What you are doing is, like @Hovercraft says in this post, separating the screen drawing from the writing to files so that you don't see your graphics drawing performance hurt.

    I have tried to make the drawing only once but you have no easy method to store the drawing Graphics object. Probably, it is implemented to prevent this. If you see the way the method works, you are given the Graphics object with the only purpose to draw on it. Using it in other ways could impact the performance.

    0 讨论(0)
  • 2021-01-27 09:53

    I was answering your question on Display to GUI and Save to Disk with a Single Object/Variable, however it was closed probably due to the similar nature of your question. I think there are several issues which you seemed confused with and I would like to write my solution here which also addresses your question in your duplicated 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?

    Don't be confused between drawing an image on the Panel and saving it. The following shows a working example on saving a drawn image.

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

    To save an image, you not necessarily have to draw and display it in the JPanel first. Note that I created a BufferedImage called buf and I am drawing on buf. Once I have drawn onto a BufferedImage, I can simply save that image as a file (I don't have to draw it to the panel first).

    Notice that I did the following:

        @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) will draw whatever on buf onto the JPanel. It can be deleted and the saving will still work. When I draw it on the panel, it is only for the user to see the outcome of the drawing.

    To test the program:

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

    Saved Image:


    Some pointers on drawing:

    • paintComponent(Graphics) shall only contain codes for drawing and nothing else. Do not implement your codes for saving the image to a file inside here.

    • Try not to create a new BufferedImage in the paintComponent(Graphics). If not, a new instance of a BufferedImage will be created on every repaint.

    0 讨论(0)
提交回复
热议问题