1

I have a problem using Graphics to put an image in a jPanel. I have the next code:

    JFileChooser navegador = new JFileChooser();
    if (navegador.showOpenDialog(null) == 0) {
        try {
            BufferedImage imagenAbrir = ImageIO.read(navegador.getSelectedFile());
            lienzo.paintComponents(imagenAbrir.getGraphics());
        } catch (IOException e) {
            JOptionPane.showMessageDialog(this, "Ocurriò un error al guardar la imàgen");
        }
    }

The code is part of a button, the user could select an imagen from any path, but it doesn't show anything in the panel. What could be the problem?

3 Answers3

3

I think you have to change you method with BufferedImage object not a Graphics object

@Override
            public void actionPerformed(ActionEvent e) {
                JFileChooser navegador = new JFileChooser();
                if (navegador.showOpenDialog(null) == 0) {
                    try {
                        BufferedImage imagenAbrir = ImageIO.read(navegador.getSelectedFile());
                        //drawPan.paintComponents(imagenAbrir.getGraphics());
                        drawPan.drawImage(imagenAbrir);
                    } catch (IOException ie) {
                        JOptionPane.showMessageDialog(null, "Ocurriò un error al guardar la imàgen");
                    }
                }
            }

Then, if you want to draw image, create customized JPanel class on your own. The paintCompoent method of JComponent will be invoked automatically, every time you call repaint method in your code.

final class ImagePane extends JPanel {

            private static final long serialVersionUID = 1L;
            private BufferedImage myImage;

            public ImagePane(final BufferedImage myImage) {
                this.myImage = myImage;
            }

            @Override
            public Dimension getPreferredSize() {
                return new Dimension(240, 220);
            }

            public void drawImage(BufferedImage img)
            {
                this.myImage = img;
                repaint();
            }

            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                if (myImage != null) {
                    Graphics2D g2d = (Graphics2D) g.create();
                    int x = (getWidth() - myImage.getWidth()) / 2;
                    int y = (getHeight() - myImage.getHeight()) / 2;
                    g2d.drawImage(myImage, x, y, this);
                    g2d.dispose();
                }
            }

        }

Here is full source code.

public class JFileChooserTest {

    static Runnable doRun = new Runnable()
    {
        final class ChooseAction implements ActionListener
        {
            final ImagePane drawPan;

            ChooseAction(final ImagePane drawPan)
            {
                this.drawPan = drawPan;
            }


            @Override
            public void actionPerformed(ActionEvent e) {
                JFileChooser navegador = new JFileChooser();
                if (navegador.showOpenDialog(null) == 0) {
                    try {
                        BufferedImage imagenAbrir = ImageIO.read(navegador.getSelectedFile());
                        //drawPan.paintComponents(imagenAbrir.getGraphics());
                        drawPan.drawImage(imagenAbrir);
                    } catch (IOException ie) {
                        JOptionPane.showMessageDialog(null, "Ocurriò un error al guardar la imàgen");
                    }
                }
            }

        }

        final class ImagePane extends JPanel {

            private static final long serialVersionUID = 1L;
            private BufferedImage myImage;

            public ImagePane(final BufferedImage myImage) {
                this.myImage = myImage;
            }

            @Override
            public Dimension getPreferredSize() {
                return new Dimension(240, 220);
            }

            public void drawImage(BufferedImage img)
            {
                this.myImage = img;
                repaint();
            }

            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                if (myImage != null) {
                    Graphics2D g2d = (Graphics2D) g.create();
                    int x = (getWidth() - myImage.getWidth()) / 2;
                    int y = (getHeight() - myImage.getHeight()) / 2;
                    g2d.drawImage(myImage, x, y, this);
                    g2d.dispose();
                }
            }

        }

        @Override
        public void run() {
            final JFrame frame = new JFrame();
            //frame.setSize(new Dimension(300,400));

            JPanel lienzo = new JPanel();
            lienzo.setLayout(new BorderLayout());

            ImagePane drawPan = new ImagePane(null);
            JButton drawMe = new JButton("draw me");
            lienzo.add(drawMe, BorderLayout.NORTH);
            lienzo.add(drawPan, BorderLayout.CENTER);

            frame.add(lienzo);

            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);

            drawMe.addActionListener(new ChooseAction(drawPan));
        }

    };

    public static void main(String[] args)
    {

        SwingUtilities.invokeLater(doRun);

    }
}

I hope this will help you.

Mickey

tommybee
  • 2,409
  • 1
  • 20
  • 23
  • Is there any other way without using drawImage()? I want it to work as Paint does, I mean, opening the file, not drawing the image, cause I have other button that does something similiar, it just adds different images, I don´t know if you get it. – David Antonio Hermosillo Solis May 10 '17 at 01:01
  • I think there is nothing difference both open image file or draw image from some resource..you can check my answer here http://stackoverflow.com/questions/37712371/how-to-use-jfilechooser-to-display-image-in-a-jframe-or-jpanel/43868678#43868678 ... The 'Browser' button reads a image file from jfilechooser class and display it. – tommybee May 10 '17 at 04:00
2

The code is part of a button, the user could select an imagen from any path, but it doesn't show anything in the panel. What could be the problem?

Basically, this is not how custom painting works in Swing. Never call paintComponent or paintComponents yourself, it's not your responsibility.

What you want to do is paint the image to the component via its Graphics context

Take a look at Painting in AWT and Swing and Performing Custom Painting for more details about how painting works and how you're suppose to use it

Then take a look at How to use lables for a simple solution for displaying images

You can also have a look at How to set a background picture in JPanel. It demonstrates using a JLabel and custom component for displaying an image

Community
  • 1
  • 1
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • I'd be interested in knowing why this would be downvoted, the OP obviously has a lack of understanding when it comes to using Swing and how it's painting process works, the best solution for which are the tutorials – MadProgrammer May 09 '17 at 06:01
  • maybe it was downvoted because some' prefer the easy way (ready to use/copy&paste code) instead of learning how to do it (tutorials to read) [:-| . Anyway +1 from me – user85421 May 09 '17 at 09:22
  • 1
    @CarlosHeuberger Forbid we teach people how to fish and become self reliant ;) – MadProgrammer May 09 '17 at 09:36
0

So, Do you want add image on the panel in which some base image is displayed? If so, there is some trick to achieve to do this. I prepare two images on the internet ( I am afraid these are licensed images )

mickey mouse mickey mouse transparent icon

Then, now i have three buttons put on your class

JButton drawMe = new JButton("draw me");
JButton pickMe = new JButton("pick me");
JButton clearMe = new JButton("clear me");

I decided to let the DrawAction class reuse with three action commands that are a draw, pick and clear together.

drawMe.addActionListener(drawAct);
drawMe.setActionCommand("draw");
pickMe.addActionListener(drawAct);
pickMe.setActionCommand("pick");
clearMe.addActionListener(drawAct);
clearMe.setActionCommand("clear");

basic gui

We'll see the ImagePane class again. If you want to add a image on a image, you should have a paintcomponent method inherited from JComponent whatever components you want to use.

The 'draw me' button is to set the base image after clearing all images in the image list in which array list of the bufferedimage class.

public void drawImage(BufferedImage img)
{
    if (imageList.size() > 0) imageList.clear();
    imageList.add(img);
    repaint();
}

The 'pick me' button is the method that add a image to the image list.

public void addImage(BufferedImage imagenAbrir) {
    imageList.add(imagenAbrir);
    repaint();
}

The last one is clear button, flush and clear all image buffers in the image list.

public void clearImage() {
     imageList.clear();
     isClear = true;
     repaint();
}

Here is my trick to clear image on the panel, it is accomplished by re-drawing canvas(jPanel at this time) with some specific color(gray). The main method, paintComponent as following..

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);

    if(isClear)
    {
        Graphics2D g2d = (Graphics2D) g.create();
        Rectangle2D rectangle = new Rectangle2D.Double(0,0,getWidth(),getHeight());
        g2d.setPaint(Color.GRAY);
        g2d.fill(rectangle);
        g2d.dispose();

        isClear = false;
        return;
    }


    if (imageList.size() > 0) {
        BufferedImage img = null;
        for(int i = 0; i < imageList.size(); i++)
        {
            img = imageList.get(i);
            Graphics2D g2d = (Graphics2D) g.create();
            int x = (getWidth() - img.getWidth()) / 2;
            int y = (getHeight() - img.getHeight()) / 2;
            g2d.drawImage(img, x, y, this);
            g2d.dispose();
        }
    }
}

Finally, you read the code below how to handle action commands along with java's component,

@Override
public void actionPerformed(ActionEvent e) {

    if(e.getActionCommand().equals("draw"))
    {
        JFileChooser navegador = new JFileChooser();
        if (navegador.showOpenDialog(null) == 0) {
            try {
                BufferedImage imagenAbrir = ImageIO.read(navegador.getSelectedFile());
                //drawPan.paintComponents(imagenAbrir.getGraphics());
                drawPan.drawImage(imagenAbrir);
            } catch (IOException ie) {
                JOptionPane.showMessageDialog(null, "Ocurrio un error al guardar la imagen");
            }
        }
    }
    else if(e.getActionCommand().equals("pick"))
    {
        JFileChooser navegador = new JFileChooser();
        if (navegador.showOpenDialog(null) == 0) {
            try {
                BufferedImage imagenAbrir = ImageIO.read(navegador.getSelectedFile());
                //drawPan.paintComponents(imagenAbrir.getGraphics());
                drawPan.addImage(imagenAbrir);
            } catch (IOException ie) {
                JOptionPane.showMessageDialog(null, "Ocurrio un error al guardar la imagen");
            }
        }
    }
    else if(e.getActionCommand().equals("clear"))
    {
        drawPan.clearImage();
    }
}

As you see the code, picking a file is required every time you click both the pick or draw me button.

open

image on image

Full source code

package com.tobee.ui.test;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class JFileChooserTest {

    static Runnable doRun = new Runnable()
    {
        final class DrawAction implements ActionListener
        {
            final ImagePane drawPan;

            DrawAction(final ImagePane drawPan)
            {
                this.drawPan = drawPan;
            }


            @Override
            public void actionPerformed(ActionEvent e) {

                System.out.println(e.getActionCommand());

                if(e.getActionCommand().equals("draw"))
                {
                    JFileChooser navegador = new JFileChooser();
                    if (navegador.showOpenDialog(null) == 0) {
                        try {
                            BufferedImage imagenAbrir = ImageIO.read(navegador.getSelectedFile());
                            //drawPan.paintComponents(imagenAbrir.getGraphics());
                            drawPan.drawImage(imagenAbrir);
                        } catch (IOException ie) {
                            JOptionPane.showMessageDialog(null, "Ocurriò un error al guardar la imàgen");
                        }
                    }
                }
                else if(e.getActionCommand().equals("pick"))
                {
                    JFileChooser navegador = new JFileChooser();
                    if (navegador.showOpenDialog(null) == 0) {
                        try {
                            BufferedImage imagenAbrir = ImageIO.read(navegador.getSelectedFile());
                            //drawPan.paintComponents(imagenAbrir.getGraphics());
                            drawPan.addImage(imagenAbrir);
                        } catch (IOException ie) {
                            JOptionPane.showMessageDialog(null, "Ocurriò un error al guardar la imàgen");
                        }
                    }
                }
                else if(e.getActionCommand().equals("clear"))
                {
                    drawPan.clearImage();
                }
            }

        }

        final class ImagePane extends JPanel {

            private static final long serialVersionUID = 1L;
            private boolean isClear;

            private List<BufferedImage> imageList;

            public ImagePane()
            {
                imageList = new ArrayList<BufferedImage>();
                isClear = false;
            }

            public void clearImage() {
                imageList.clear();
                isClear = true;
                repaint();
            }

            public void addImage(BufferedImage imagenAbrir) {
                imageList.add(imagenAbrir);
                repaint();
            }

            @Override
            public Dimension getPreferredSize() {
                return new Dimension(240, 220);
            }

            public void drawImage(BufferedImage img)
            {
                if (imageList.size() > 0) imageList.clear();
                imageList.add(img);
                repaint();
            }

            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);

                if(isClear)
                {
                    Graphics2D g2d = (Graphics2D) g.create();
                    Rectangle2D rectangle = new Rectangle2D.Double(0,0,getWidth(),getHeight());
                    g2d.setPaint(Color.GRAY);
                    g2d.fill(rectangle);
                    g2d.dispose();

                    isClear = false;
                    return;
                }


                if (imageList.size() > 0) {
                    BufferedImage img = null;
                    for(int i = 0; i < imageList.size(); i++)
                    {
                        img = imageList.get(i);
                        Graphics2D g2d = (Graphics2D) g.create();
                        int x = (getWidth() - img.getWidth()) / 2;
                        int y = (getHeight() - img.getHeight()) / 2;
                        g2d.drawImage(img, x, y, this);
                        g2d.dispose();
                    }
                }
            }

        }

        @Override
        public void run() {
            final JFrame frame = new JFrame();

            JPanel lienzo = new JPanel();
            lienzo.setLayout(new BorderLayout());


            JPanel optionPan = new JPanel();
            ImagePane drawPan = new ImagePane();
            JButton drawMe = new JButton("draw me");
            JButton pickMe = new JButton("pick me");
            JButton clearMe = new JButton("clear me");

            DrawAction drawAct = new DrawAction(drawPan);

            optionPan.add(drawMe);
            optionPan.add(pickMe);
            optionPan.add(clearMe);

            lienzo.add(optionPan, BorderLayout.NORTH);
            lienzo.add(drawPan, BorderLayout.CENTER);

            frame.add(lienzo);

            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);

            drawMe.addActionListener(drawAct);
            drawMe.setActionCommand("draw");
            pickMe.addActionListener(drawAct);
            pickMe.setActionCommand("pick");
            clearMe.addActionListener(drawAct);
            clearMe.setActionCommand("clear");
        }

    };

    public static void main(String[] args)
    {

        SwingUtilities.invokeLater(doRun);

    }
}
tommybee
  • 2,409
  • 1
  • 20
  • 23