JLabel Image Refresh - Issues
The part of the application that I am currently having trouble with is able to scroll and display a list of images one at a time. I am getting a directory from the user by buffering all the files in that directory and then loading an array with only jpegs and png. Then I want to update the JLabel with the first image and provide the previous and next buttons to scroll and display each image in turn. When I try to display the second image it doesn't update ... Here's what I have so far:
public class CreateGallery
{
private JLabel swingImage;
The method I am using to update the image:
protected void updateImage(String name)
{
BufferedImage image = null;
Image scaledImage = null;
JLabel tempImage;
try
{
image = ImageIO.read(new File(name));
} catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
// getScaledImage returns an Image that been resized proportionally to my thumbnail constraints
scaledImage = getScaledImage(image, THUMB_SIZE_X, THUMB_SIZE_Y);
tempImage = new JLabel(new ImageIcon(scaledImage));
swingImage = tempImage;
}
Then, in my createAndShowGUI method, which puts the swingImage in ...
private void createAndShowGUI()
{
//Create and set up the window.
final JFrame frame = new JFrame();
// Miscellaneous code in here - removed for brevity
// Create the Image Thumbnail swingImage and start up with a default image
swingImage = new JLabel();
String rootPath = new java.io.File("").getAbsolutePath();
updateImage(rootPath + "/images/default.jpg");
// Miscellaneous code in here - removed for brevity
rightPane.add(swingImage, BorderLayout.PAGE_START);
frame.add(rightPane, BorderLayout.LINE_END);
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
UIManager.put("swing.boldMetal", Boolean.FALSE);
new CreateGalleryXML().createAndShowGUI();
}
});
}
If you've gotten to this, the first image is my default.jpg, and once I get the directory and identify the first image in that directory, that's where it fails when I try to update swingImage. Now I have tried doing swingImage.setVisible () and swingImage.revalidate () to try and get it to reload. I am guessing that my tempImage = new JLabel is the root cause. But I'm not sure how to convert my BufferedImage or Image to JLabel in order to just update the swingImage.
source to share
Instead of creating one New Instance
for JLabel
each, Image
just use the JLabel # setIcon (...) method JLabel
to change the image.
Small sample program:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class SlideShow extends JPanel
{
private int i = 0;
private Timer timer;
private JLabel images = new JLabel();
private Icon[] icons = {UIManager.getIcon("OptionPane.informationIcon"),
UIManager.getIcon("OptionPane.errorIcon"),
UIManager.getIcon("OptionPane.warningIcon")};
private ImageIcon pictures1, pictures2, pictures3, pictures4;
private ActionListener action = new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
i++;
System.out.println(i);
if(i == 1)
{
pictures1 = new ImageIcon("image/caIcon.png");
images.setIcon(icons[i - 1]);
System.out.println("picture 1 should be displayed here");
}
if(i == 2)
{
pictures2 = new ImageIcon("image/Keyboard.png");
images.setIcon(icons[i - 1]);
System.out.println("picture 2 should be displayed here");
}
if(i == 3)
{
pictures3 = new ImageIcon("image/ukIcon.png");
images.setIcon(icons[i - 1]);
System.out.println("picture 3 should be displayed here");
}
if(i == 4)
{
pictures4 = new ImageIcon("image/Mouse.png");
images.setIcon(icons[0]);
System.out.println("picture 4 should be displayed here");
}
if(i == 5)
{
timer.stop();
System.exit(0);
}
revalidate();
repaint();
}
};
public SlideShow()
{
JFrame frame = new JFrame("SLIDE SHOW");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationByPlatform(true);
frame.getContentPane().add(this);
add(images);
frame.setSize(300, 300);
frame.setVisible(true);
timer = new Timer(2000, action);
timer.start();
}
public static void main(String... args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new SlideShow();
}
});
}
}
Since you are doing this with ImageIO, here is a good example related to this JLabel using ImageIO
Information relevant to your case, as to what is happening:
Inside your method, createAndShowGUI()
you initialize your JLabel
(swingImage), and you add it to yours JPanel
, which indirectly refers to JFrame
.
But now in your method updateImage()
you are initializing a new one JLabel
, now it is in some other memory location by writing tempImage = new JLabel(new ImageIcon(scaledImage));
and after that you will point yours swingImage(JLabel)
to point to this newly created one JLabel
, but this newly created one was JLabel
never added JPanel
at any point. Hence, it will not be visible even if you try revalidate()/repaint()/setVisible(...)
. Hence, either you change the code for your method updateImage(...)
to this:
protected void updateImage(String name)
{
BufferedImage image = null;
Image scaledImage = null;
JLabel tempImage;
try
{
image = ImageIO.read(new File(name));
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
// getScaledImage returns an Image that been resized
// proportionally to my thumbnail constraints
scaledImage = getScaledImage(image, THUMB_SIZE_X, THUMB_SIZE_Y);
tempImage = new JLabel(new ImageIcon(scaledImage));
rightPane.remove(swingImage);
swingImage = tempImage;
rightPane.add(swingImage, BorderLayout.PAGE_START);
rightPane.revalidate();
rightPane.repaint(); // required sometimes
}
Or use JLabel.setIcon(...)
as mentioned earlier :-)
UPDATED ANSWER
Here, see how it New JLabel
fits into the position of the old,
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class SlideShow extends JPanel
{
private int i = 0;
private Timer timer;
private JLabel images = new JLabel();
private Icon[] icons = {UIManager.getIcon("OptionPane.informationIcon"),
UIManager.getIcon("OptionPane.errorIcon"),
UIManager.getIcon("OptionPane.warningIcon")};
private ActionListener action = new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
i++;
System.out.println(i);
if(i == 4)
{
timer.stop();
System.exit(0);
}
remove(images);
JLabel temp = new JLabel(icons[i - 1]);
images = temp;
add(images);
revalidate();
repaint();
}
};
private void createAndDisplayGUI()
{
JFrame frame = new JFrame("SLIDE SHOW");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationByPlatform(true);
this.setLayout(new FlowLayout(FlowLayout.LEFT));
add(images);
frame.getContentPane().add(this, BorderLayout.CENTER);
frame.setSize(300, 300);
frame.setVisible(true);
timer = new Timer(2000, action);
timer.start();
}
public static void main(String... args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new SlideShow().createAndDisplayGUI();
}
});
}
}
And for your question: Of the two options I've tried, is one better than the other?
setIcon(...)
has an edge in a different path, meaning you don't have to worry about the revalidate () / repaint () thingy after adding / removing JLabel
. Plus, you don't have to remember your placement JLabel
every time you add it. It stays in that position, and you just call one method to change the image, no strings attached and no work, no headaches.
And for question 2: I had a little doubt as to which is Array of Records
?
source to share