7 Replies Latest reply on May 12, 2009 5:51 AM by darrylburke

    My program always displays the same image, even when I change th image file

    807588
      I'm making a program that chooses an image file from a dialog, resize it and copy it into a folder. When the image is needed to be displayed, the image file is read and a JLabel displays it on screen.

      When I upload the first image, everything works fine. The problem appears when I upload another picture: the displayed image is still the first image, even when the old file doesn't exist anymore (because it has been overwritten). It looks like the image has been "cached", and no more image are loaded after the first one.

      This function takes the image picture chosen by the user, resizes it, and copy it into the pictures folder:
          private void changeProfilePicture() {
              JFileChooser jFileChooser = new JFileChooser();
              jFileChooser.setMultiSelectionEnabled(false);
              jFileChooser.setFileFilter(new ImageFileFilter());
              int result = jFileChooser.showOpenDialog(sdbFrame);
              if (JFileChooser.APPROVE_OPTION == result) {
                  try {
                      //upload picture
                      File file = jFileChooser.getSelectedFile();
                      InputStream is = new BufferedInputStream(new FileInputStream(file));
                      //resize image and save
                      BufferedImage image = ImageIO.read(is);
                      BufferedImage resizedImage = resizeImage(image, 96, 96);
                      String newFileName = sdbDisplayPanel.getId() + ".png";
                      String picFolderLocation = db.getDatabaseLocation() + "/" +
                              PROFILE_PICTURE_FOLDER;
                      java.io.File dbPicFolder = new File(picFolderLocation);
                      if(!dbPicFolder.exists())  {
                          dbPicFolder.mkdir();
                      }
                      String newFilePath = picFolderLocation + "/" + newFileName;
                      File newFile = new File(newFilePath);
      
                      FileOutputStream fos = new FileOutputStream (newFilePath);
                      DataOutputStream dos = new DataOutputStream (fos);
                      ImageIO.write(resizedImage, "png", dos);
                      dos.close();
                      fos.close();
      
                      //set picture
                      sdbDisplayPanel.setImagePath(newFilePath);
                  } catch (IOException ex) {
                      System.err.println("Could'nt print picture");
                  }
      This other class actually displays the image file in a JLabel:
          public void setImagePath(String imagePath) {
              count++;
              speaker.setImagePath(imagePath);
              this.imagePath = imagePath;
              if(imagePath != null)   {
                  //use uploaded picture
                  try {
                      File tempFile = new File(imagePath);
                      System.out.println(tempFile.length());
                      java.net.URL imgURL = tempFile.toURI().toURL();
                      ImageIcon icon = new ImageIcon(imgURL);
                      pictureLbl.setIcon(icon);
                      // Read from a file
                  } catch (IOException ex) {
                      Logger.getLogger(SDBEventClass.class.getName()).log(Level.SEVERE, null, ex);
                  }
              }
              else    {
                  //use default picture
                  URL imgURL = this.getClass().getResource("/edu/usal/dia/adilo/images/noProfile.jpg");
                  ImageIcon icon = new ImageIcon(imgURL, "Profile picture");
                  pictureLbl.setIcon(icon);
              }
          }
        • 1. Re: My program always displays the same image, even when I change th image
          807588
          Hi Jurafsky,

          Try this at the end of your changeProfilePicture() method:
          sdbDisplayPanel.repaint();
          Setting the image file path doesn't do everything; you also need to tell the panel to show that new picture.

          Hope that helps,
          Jezzica85
          • 2. Re: My program always displays the same image, even when I change th image
            807588
            Hi jezzica85. Thanks for the quick answer. :)

            The repaint it's not the problem, because it works perfectly when I read images from a different source. The problem appears when I try to read the same file after overwriting it with a new image. The old image that I had before the overwriting is displayed, instead of the new one. That's why I said the image looks like "cached".

            Any ideas?
            • 3. Re: My program always displays the same image, even when I change th image
              camickr
              you also need to tell the panel to show that new picture.
              Swing components are smart enough to repaint themselves when a property changes. So all you need to do is use the setIcon(...) method.
              That's why I said the image looks like "cached".
              Yes, the image is cached. You should be able to use ImageIO.read(...) to force reading of the new image.
              • 4. Re: My program always displays the same image, even when I change th image file
                darrylburke
                ImageIcon loads the image via Toolkit, and Toolkit caches the images so won't normally reload a new image from the same path/URL.

                You have two options here: either invoke Image#flush() to force reloading of the new image, or load your images using ImageIO#read(...) and use a form of ImageIcon constuctor that takes an Image as an argument.

                db
                • 5. Re: My program always displays the same image, even when I change th image
                  807588
                  SOLVED!! Thank you camickr, it worked! :D

                  If anyone ends up here with the same problem, when you're reading multiple times an image from a file, and this file may change, you must avoid this code
                  File file = new File(imagePath);
                  java.net.URL imgURL = file.toURI().toURL();
                  ImageIcon icon = new ImageIcon(imgURL);
                  pictureLabel.setIcon(icon);
                  and use this one in order to skip the image caching.
                  File file = new File(imagePath);
                  BufferedImage image = ImageIO.read(file);
                  ImageIcon icon = new ImageIcon(image);
                  pictureLabel.setIcon(icon);
                  • 6. Re: My program always displays the same image, even when I change th image file
                    807588
                    Thanks Darryl, your other option worked as well: :)
                    File file = new File(imagePath);
                    java.net.URL imgURL = file.toURI().toURL();
                    ImageIcon icon = new ImageIcon(imgURL);
                    icon.getImage().flush();
                    pictureLabel.setIcon(icon);
                    • 7. Re: My program always displays the same image, even when I change th image file
                      darrylburke
                      When you flush() the image, you don't need to construct a new ImageIcon each time, a simple repaint() will suffice.

                      Run this example after changing the URL to an image you can edit and update while the program is running.
                      import java.awt.BorderLayout;
                      import java.awt.Image;
                      import java.awt.event.ActionEvent;
                      import java.awt.event.ActionListener;
                      import java.net.MalformedURLException;
                      import java.net.URL;
                      import javax.swing.*;
                      
                      public class FlushImage {
                      
                         Image image;
                         JLabel label;
                      
                         public static void main(String[] args) {
                            SwingUtilities.invokeLater(new Runnable() {
                      
                               @Override
                               public void run() {
                                  new FlushImage().makeUI();
                               }
                            });
                         }
                      
                         public void makeUI() {
                            try {
                               ImageIcon icon = new ImageIcon(new URL("file:///e:/java/dot.png"));
                               image = icon.getImage();
                               label = new JLabel(icon);
                               
                               JButton button = new JButton("Click");
                               button.addActionListener(new ActionListener() {
                      
                                  public void actionPerformed(ActionEvent e) {
                                     image.flush();
                                     label.repaint();
                                  }
                               });
                      
                               JFrame frame = new JFrame("");
                               frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                               frame.add(label, BorderLayout.NORTH);
                               frame.add(button, BorderLayout.SOUTH);
                               frame.pack();
                               frame.setLocationRelativeTo(null);
                               frame.setVisible(true);
                            } catch (MalformedURLException ex) {
                               ex.printStackTrace();
                            }
                         }
                      }
                      db