Swing JMenuItem - Icons not showing up [duplicate] - java

I am having a error for my GUI. Trying to set title bar icon then be included in a Runnable JAR.
BufferedImage image = null;
try {
image = ImageIO.read(getClass().getClassLoader().getResource("resources/icon.gif"));
}
catch (IOException e) {
e.printStackTrace();
}
frame.setIconImage(image);
Here is the error I am getting:
Exception in thread "main" java.lang.IllegalArgumentException: input == null!
at javax.imageio.ImageIO.read(Unknown Source)
at GUI.<init>(GUI.java:39)
at GUI.main(GUI.java:351)
The image is in the correct directory which "resources" folder is the root of the
project file

First of all, change this line :
image = ImageIO.read(getClass().getClassLoader().getResource("resources/icon.gif"));
to this :
image = ImageIO.read(getClass().getResource("/resources/icon.gif"));
More info, on as to where lies the difference between the two approaches, can be found on this thread - Different ways of loading a Resource
For Eclipse:
How to add Images to your Resource Folder in the Project
For NetBeans:
Handling Images in a Java GUI Application
How to add Images to the Project
For IntelliJ IDEA:
Right-Click the src Folder of the Project. Select New -> Package
Under New Package Dialog, type name of the package, say resources. Click OK
Right Click resources package. Select New -> Package
Under New Package Dialog, type name of the package, say images. Click OK
Now select the image that you want to add to the project, copy it. Right click resources.images package, inside the IDE, and select Paste
Use the last link to check how to access this file now in Java code. Though for this example, one would be using
getClass().getResource("/resources/images/myImage.imageExtension");
Press Shift + F10, to make and run the project. The resources and images folders, will be created automatically inside the out folder.
If you are doing it manually :
How to add Images to your Project
How to Use Icons
A Little extra clarification, as given in this answer's first
code example.
QUICK REFERENCE CODE EXAMPLE(though for more detail consider, A little extra clarification link):
package swingtest;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.*;
/**
* Created with IntelliJ IDEA.
* User: Gagandeep Bali
* Date: 7/1/14
* Time: 9:44 AM
* To change this template use File | Settings | File Templates.
*/
public class ImageExample {
private MyPanel contentPane;
private void displayGUI() {
JFrame frame = new JFrame("Image Example");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
contentPane = new MyPanel();
frame.setContentPane(contentPane);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private class MyPanel extends JPanel {
private BufferedImage image;
public MyPanel() {
try {
image = ImageIO.read(MyPanel.class.getResource("/resources/images/planetbackground.jpg"));
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
return image == null ? new Dimension(400, 300): new Dimension(image.getWidth(), image.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, this);
}
}
public static void main(String[] args) {
Runnable runnable = new Runnable() {
#Override
public void run() {
new ImageExample().displayGUI();
}
};
EventQueue.invokeLater(runnable);
}
}

There's a much easier way to load and set an image as a frame icon:
frame.setIconImage(
new ImageIcon(getClass().getResource("/resources/icon.gif")).getImage());
And thats all :)! You don't even have to use a try-catch block because ImageIcon does not throw any declared exceptions. And due to getClass().getResource(), it works both from file system and from a jar depending how you run your application.
If you need to check whether the image is available, you can check if the URL returned by getResource() is null:
URL url = getClass().getResource("/resources/icon.gif");
if (url == null)
System.out.println( "Could not find image!" );
else
frame.setIconImage(new ImageIcon(url).getImage());

The image files must be in the directory resources/ in your JAR, as shown in How to Use Icons and this example for the directory named images/.

Related

Easily print image on the screen for debug purposes in a blocking manner

I am working on a computer vision project and somewhere in a process an endless loop happens. It seems that my image data is being corrupted.
In past, I used to save debug results on the disk using this method:
public static boolean saveToPath(String path, BufferedImage image) {
File img = new File(path);
try {
ImageIO.write(image, "png", new File(path));
} catch (IOException ex) {
System.err.println("Failed to save image as '"+path+"'. Error:"+ex);
return false;
}
return true;
}
The problem is that once loops are used and the error is somewhere inbetween, I need to see many images. So basically, I'd like a method that would be defined like this:
/** Displays image on the screen and stops the execution until the window with image is closed.
*
* #param image image to be displayed
*/
public static void printImage(BufferedImage image) {
???
}
And could be called in a loop or any function to show be the actual image, effectively behaving like a break point. Because while multithreading is very good in production code, blocking functions are much better for debugging.
You can code something like this. In this example, the image file has to be in the same directory as the source code.
Here's the image displayed in a dialog. You left click the OK button to continue processing.
If the image is bigger than your screen, scroll bars will appear to let you see the whole image.
In your code, since you already have the Image, you can just copy and paste the displayImage method.
package com.ggl.testing;
import java.awt.Image;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
public class DisplayImage {
public DisplayImage() {
displayImage(getImage());
}
private Image getImage() {
try {
return ImageIO.read(getClass().getResourceAsStream(
"StockMarket.png"));
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
public void displayImage(Image image) {
JLabel label = new JLabel(new ImageIcon(image));
JPanel panel = new JPanel();
panel.add(label);
JScrollPane scrollPane = new JScrollPane(panel);
JOptionPane.showMessageDialog(null, scrollPane);
}
public static void main(String[] args) {
new DisplayImage();
}
}

Eclipse exported jar file just shows a black Jpanel

I am working on a java game and the game works perfectly in eclipse, but when I exported is as a runnable jar file it did not work. Only a black window showed up.
My game has a splash screen which changes to menu screen after few seconds. the splash screen sconsists of an BufferedImage (in jpg) but the menu screen also consists of a Graphics2D writing. Few seconds after running the jar file the writing doesn't show up, so I think image formats and such might not be the issue.
I'm quite confused and frustrated so any help would be appriciated.
It turned out the problem is in my use of Timer, this is my source of the splashscreen
package GameState;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.Timer;
import Main.GamePanel;
public class SplashState extends GameState implements ActionListener{
private BufferedImage image;
private Timer timer;
public SplashState(GameStateManager gsm) {
this.gsm = gsm;
try {
image = ImageIO.read(new File("Resources/Backgrounds/block.jpg"));
timer = new Timer(2000, this);
timer.setRepeats(false);
timer.start();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void init() {
}
public void update() {
}
public void draw(Graphics2D g) {
g.drawImage(image, (GamePanel.WIDTH-image.getWidth())/2, (GamePanel.HEIGHT-image.getHeight())/2, null);
}
public void keyPressed(int k) {
}
public void keyReleased(int k) {}
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
gsm.setState(GameStateManager.MENUSTATE);
timer.stop();
}
}
I still don't know what's wrong so any help would be appriciated
I've had a similar problem in the past, and it was due to the way Eclipse was packaging the required libraries into the jar. I would bet you have it set to "Extract required libraries into generated jar", and you should set it to "Package required libraries into generated jar". To do this, right click on project -> Export -> Java -> Runnable Jar File. Then click next, and select the radio button for "Package required libraries into generated jar". This should fix your problem.
If you are writing to an image, the image must be outside of the jar file, because you cannot edit a jar file while it is running. If this is the case, you may want to make a folder that contains your jar and the images it will write to.

ImageIcon not rendering for animation

I have tried to look at other topics with similar question like mine, and most of those solutions appear to point to fixing the classpath for images... so, I tried those by changing the classpath to absolute and using class get resource, but it still won't render the images. I have a suspicion that it has to do with the main method. I don't completely understand how that method works since I copied the source code somewhere online. I am using the Eclipse editor, and I already had put the image files alongside the Flap class file.
package wing;
import java.awt.*;
import javax.swing.*;
public class Flap extends JComponent implements Runnable {
Image[] images = new Image[2];
int frame = 0;
public void paint(Graphics g) {
Image image = images[frame];
if (image != null) {
// Draw the current image
int x = 0;
int y = 0;
g.drawImage(image, x, y, this);
}
}
public void run() {
// Load the array of images
images[0] = new ImageIcon(this.getClass().getResource("/Wing/src/wing/wing1.png"));
images[1] = new ImageIcon(this.getClass().getResource("/Wing/src/wing/wing2.png"));
// Display each image for 1 second
int delay = 10000; // 1 second
try {
while (true) {
// Move to the next image
frame = (frame+1)%images.length;
// Causes the paint() method to be called
repaint();
// Wait
Thread.sleep(delay);
}
} catch (Exception e) {
}
}
public static void main(String[] args) {
Flap app = new Flap();
// Display the animation in a frame
JFrame frame = new JFrame();
frame.getContentPane().add(app);
frame.setSize(800, 700);
frame.setVisible(true);
(new Thread(app)).start();
}
}
ImageIcon is not an Image :
images[0] = new ImageIcon(this.getClass().getResource("/Wing/src/wing/wing1.png")).getImage();
The application never ends, in main :
frame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
if isn't there any another JComponent(s) added to the public class Flap extends JComponent implements Runnable {
put Image as Icon to the JLabel
use Swing Timer instead of Runnable#Thread (required basic knowledge about Java and Threads too)
if there is/are another JComponent(s) added to the public class Flap extends JComponent implements Runnable {
don't use paint() use paintComponent() for Swing JComponents
use Swing Timer instead of Runnable#Thread (required basic knowledge about Java and Threads too)
in both cases load image as local variable, don't reload images forever
in both cases you have invoke Swing GUI from InitialThread
The resource name "/Wing/src/wing/wing1.png" looks suspicious: it means to locate a resource in the "/Wing/src/wing/" directory, which is most likely not where the resource actually is. Try "/wing/wing1.png" (similarly for the others)
The reason is that the src folder contains the source, which will be converted to classes. So "src/wing/Flap.java" will have the class path "/wing/Flap.class"; similarly for resources (depending on how you are packaging them).
Also, make sure the resource is indeed where you expect it to be (e.g. next to the Flap.class file in the output directory), otherwise the class loader will not find it.

How do I add an image to a JButton

I am trying to add an image to a JButton and I'm not sure what I'm missing. When I run the following code the button looks exactly the same as if I had created it without any image attribute. Water.bmp is in the root of my project folder.
ImageIcon water = new ImageIcon("water.bmp");
JButton button = new JButton(water);
frame.add(button);
I think that your problem is in the location of the image. You shall place it in your source, and then use it like this:
JButton button = new JButton();
try {
Image img = ImageIO.read(getClass().getResource("resources/water.bmp"));
button.setIcon(new ImageIcon(img));
} catch (Exception ex) {
System.out.println(ex);
}
In this example, it is assumed that image is in src/resources/ folder.
#Rogach
and you may like to add:
// to remote the spacing between the image and button's borders
button.setMargin(new Insets(0, 0, 0, 0));
// to add a different background
button.setBackground( ... );
// to remove the border
button.setBorder(null);
It looks like a location problem because that code is perfectly fine for adding the icon.
Since I don't know your folder structure, I suggest adding a simple check:
File imageCheck = new File("water.bmp");
if(imageCheck.exists())
System.out.println("Image file found!")
else
System.out.println("Image file not found!");
This way if you ever get your path name wrong it will tell you instead of displaying nothing. Exception should be thrown if file would not exist, tho.
You put your image in resources folder and use follow code:
JButton btn = new JButton("");
btn.setIcon(new ImageIcon(Class.class.getResource("/resources/img.png")));
public class ImageButton extends JButton {
protected ImageButton(){
}
#Override
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
Image img = Toolkit.getDefaultToolkit().getImage("water.bmp");
g2.drawImage(img, 45, 35, this);
g2.finalize();
}
}
OR use this code
class MyButton extends JButton {
Image image;
ImageObserver imageObserver;
MyButtonl(String filename) {
super();
ImageIcon icon = new ImageIcon(filename);
image = icon.getImage();
imageObserver = icon.getImageObserver();
}
public void paint( Graphics g ) {
super.paint( g );
g.drawImage(image, 0 , 0 , getWidth() , getHeight() , imageObserver);
}
}
I did only one thing and it worked for me .. check your code is this method there ..
setResizable(false);
if it false make it true and it will work just fine ..
I hope it helped ..
buttonB.setIcon(new ImageIcon(this.getClass().getResource("imagename")));
//paste required image on C disk
JButton button = new JButton(new ImageIcon("C:water.bmp");
This code work for me:
BufferedImage image = null;
try {
URL file = getClass().getResource("water.bmp");
image = ImageIO.read(file);
} catch (IOException ioex) {
System.err.println("load error: " + ioex.getMessage());
}
ImageIcon icon = new ImageIcon(image);
JButton quitButton = new JButton(icon);
For example if you have image in folder res/image.png you can write:
try
{
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream input = classLoader.getResourceAsStream("image.png");
// URL input = classLoader.getResource("image.png"); // <-- You can use URL class too.
BufferedImage image = ImageIO.read(input);
button.setIcon(new ImageIcon(image));
}
catch(IOException e)
{
e.printStackTrace();
}
In one line:
try
{
button.setIcon(new ImageIcon(ImageIO.read(Thread.currentThread().getContextClassLoader().getResourceAsStream("image.png"))));
}
catch(IOException e)
{
e.printStackTrace();
}
If the image is bigger than button then it will not shown.
eclipse example:
After reading the above, it still took me more research to understand, where and how to place image resources, using eclipse.
The outcome: in eclipse you need to store images underneath any "Source Folder" (such as "src") or below in a "Folder".
You create both by right-clicking on your project, "New"->"Source Folder" or "New"->"Folder". Any folder name is fine. Examples for "<Source Folder>/<image Folder>" are "src/images" or "resource/img".
Here's some fully functioning sample code, which expects two button images, "Button-Image-Up.png" and "Button-Image-Down.png" in folder "images":
import javax.swing.JDialog;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
#SuppressWarnings("serial")
public class ImageButtonDlg extends JDialog {
// define button images and fall-back text
private static gstrTxt="<Button Fall-back Text>"; // in case image does not load
private static String gstrImgUp="Button-Image-Up.png"; // regular image
private static String gstrImgDown="Button-Image-Down.png"; // button pressed image
private static String gstrImgFolder="images"; // image folder, "/images" is also fine
public static void main(String[] args) {
ImageButtonDlg dialog = new ImageButtonDlg();
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dialog.setVisible(true);
}
/**
* Create the dialog.
*/
public ImageButtonDlg() {
initializeDialog();
}
/**
* Create a new ImageIcon from an image resource.
* The input can be:
* - an image file name, e.g. <image.png>
* - a relative path, e.g. <image/image.png>
* - an absolute path, e.g. </home/user/dev/image.png>
* In eclipse, images can be stored below any project "Source folder",
* such as "src".
* ├── src
* │   ├── img1.png
* │   └── images
* │      └── img2.png
* ├── resources
* │   ├── img3.png
* │   └── images
* │      └── img4.png
* └── img5.png
* In above example img1.png to img4.png are found by
* image file name or relative path
* However, img5 is stored in the project root folder and
* needs an absolute path.
*
* #param strImagePath - image filename, absolute path or relative path
* #return new ImageIcon or 'null' if load fails
*/
public static ImageIcon getResourceImageIcon(String strFilepath) {
ClassLoader loader = null;
URL url = null;
Image img=null;
ImageIcon imgIcon=null;
loader = ImageButtonDlg.class.getClassLoader();
System.out.println(loader.toString());
try { // file location: <a relative path>
url = loader.getResource("images/"+strFilepath);
if(url==null) {
System.out.printf("ImageButtonDlg.class.getResource(%s)=>null\n", "images/"+strFilepath);
}
} catch (Exception e0) {
e0.printStackTrace();
}
if(url==null) {
try { // file location: <image filename>
url = loader.getResource(strFilepath);
if(url==null) {
System.out.printf("Util.class.getResource(%s)=>null\n", strFilepath);
}
} catch (Exception e1) {
e1.printStackTrace();
}
}
try {
img = ImageIO.read(url);
} catch (Exception e2) {
e2.printStackTrace();
System.exit(0);
}
if (img!=null){
imgIcon = new ImageIcon(img);
}
return imgIcon;
}
/**
* Create JButton with Image
* In case Image load fails, we create a JButton with text
* #param strImgPath - path to Image
* #param strAltText - fall-back text
* #return
*/
public static JButton getNewJButtonWithImageIcon(String strImgPath, String strAltText) {
JButton btnReturn = null;
ImageIcon imgIcon = getResourceImageIcon(strImgPath);
if (imgIcon!=null){
btnReturn = new JButton(imgIcon);
}
else {
btnReturn = new JButton(strAltText);
}
return btnReturn;
}
/**
* Image button was pressed, display a message box
*/
private void actionImageButtonPressed() {
try {
JOptionPane.showMessageDialog(null, "Image Button was pressed", "Info", JOptionPane.INFORMATION_MESSAGE);
}
catch (Exception e) {
; // ignore
}
}
/**
* Initialize the dialog
* add a button panel and the image button to the window/content pane
*/
private void initializeDialog()
{
this.setTitle("Image Button Example");
this.setResizable(false);
this.setBounds(200, 200, 699, 601);
JPanel panelButton = new JPanel();
panelButton.setLayout(new FlowLayout(FlowLayout.RIGHT)); // all buttons in a row
getContentPane().add(panelButton, BorderLayout.SOUTH); // button pane at the bottom of the window
// create the Image Button
JButton btnImageButton = getNewJButtonWithImageIcon(gstrImgUp, gstrTxt);
btnImageButton.setToolTipText("<Explain what pressing the Button does>");
btnImageButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
actionImageButtonPressed();// The Action
}
});
// load button image when button clicked/released
btnImageButton.addMouseListener((MouseListener) new MouseAdapter() {
public void mousePressed(MouseEvent e) {
btnImageButton.setIcon(getResourceImageIcon(gstrImgDown));
}
public void mouseReleased(MouseEvent e) {
btnImageButton.setIcon(getResourceImageIcon(gstrImgUp));
}
});
btnImageButton.setActionCommand("ImageButtonAction");
// add button to button panel
panelButton.add(btnImageButton);
}
}
Have Fun!
Volker Fröhlich
P.S.:
Perhaps someone can share additional practical experience.
In eclipse "WindowBuilder Editor" such image buttons are shown, but they cannot be accessed - is there some workaround?
What is the NetBeans approach, if any different?

making jfilechooser show image thumbnails

I wanted to create a JFileChooser with thumbnail view of image files.So I subclassed FileView and in the method which creates ImageIcon did some scaling sothat thumbnail images are shown.
However,the overall effect is that, the filechooser widget takes some time before opening a directory and showing thumbnails..In createImageIcon() below,I need to call new ImageIcon() twice-once with the image filepath and next with the resized image as constructor argument.I think this is what slows the widget .
Is there a more efficient alternative?Any suggestions/pointers most welcome.
thanks,
mark
public static void main(String[] args) {
JFileChooser chooser=new JFileChooser();
ThumbNailView thumbView=new ThumbNailView();
chooser.setFileView(thumbView);
}
class ThumbNailView extends FileView{
public Icon getIcon(File f){
Icon icon=null;
if(isImageFile(f.getPath())){
icon=createImageIcon(f.getPath(),null);
}
return icon;
}
private ImageIcon createImageIcon(String path,String description) {
if (path != null) {
ImageIcon icon=new ImageIcon(path);
Image img = icon.getImage() ;
Image newimg = img.getScaledInstance( 16, 16, java.awt.Image.SCALE_SMOOTH ) ;
return new ImageIcon(newimg);
} else {
System.err.println("Couldn't find file: " + path);
return null;
}
}
private boolean isImageFile(String filename){
//return true if this is image
}
I was actually surprised to see that, despite using the native look & feel in Windows, the file chooser indeed doesn't have a thumbnail view. I tried your example and you're going along the right lines, but I see how slow it was for folders with a lot of large images. The overhead is, of course, due to I/O when reading the file contents and then interpreting the image, which is unavoidable.
What's even worse, is that I found out that FileView.getIcon(File) is called a lot - before the file list is shown, when you mouse over an icon, and when the selection changes. If we don't cache the images after loading them, we'll be pointlessly reloading images all the time.
The obvious solution is to push all the image loading off onto another thread or a thread pool, and once we have our scaled-down result, put it into a temporary cache so it can be retrieved again.
I played around with Image and ImageIcon a lot and I discovered that an ImageIcon's image can be changed at any time by calling setImage(Image). What this means for us is, within getIcon(File), we can immediately return a blank or default icon, but keep a reference to it, passing it along to a worker thread that will load the image in the background and set the icon's image later when it's done (The only catch is that we must call repaint() to see the change).
For this example, I'm using an ExecutorService cached thread pool (this is the fastest way to get all images, but uses a lot of I/O) to process the image loading tasks. I'm also using a WeakHashMap as the cache, to ensure that we only hold onto the cached icons for as long as we need them. You could use another kind of Map, but you would have to manage the number of icons you hold onto, to avoid running out of memory.
package guitest;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.regex.Pattern;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.filechooser.FileView;
public class ThumbnailFileChooser extends JFileChooser {
/** All preview icons will be this width and height */
private static final int ICON_SIZE = 16;
/** This blank icon will be used while previews are loading */
private static final Image LOADING_IMAGE = new BufferedImage(ICON_SIZE, ICON_SIZE, BufferedImage.TYPE_INT_ARGB);
/** Edit this to determine what file types will be previewed. */
private final Pattern imageFilePattern = Pattern.compile(".+?\\.(png|jpe?g|gif|tiff?)$", Pattern.CASE_INSENSITIVE);
/** Use a weak hash map to cache images until the next garbage collection (saves memory) */
private final Map imageCache = new WeakHashMap();
public static void main(String[] args) throws Exception {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
JFileChooser chooser = new ThumbnailFileChooser();
chooser.showOpenDialog(null);
System.exit(1);
}
public ThumbnailFileChooser() {
super();
}
// --- Override the other constructors as needed ---
{
// This initializer block is always executed after any constructor call.
setFileView(new ThumbnailView());
}
private class ThumbnailView extends FileView {
/** This thread pool is where the thumnnail icon loaders run */
private final ExecutorService executor = Executors.newCachedThreadPool();
public Icon getIcon(File file) {
if (!imageFilePattern.matcher(file.getName()).matches()) {
return null;
}
// Our cache makes browsing back and forth lightning-fast! :D
synchronized (imageCache) {
ImageIcon icon = imageCache.get(file);
if (icon == null) {
// Create a new icon with the default image
icon = new ImageIcon(LOADING_IMAGE);
// Add to the cache
imageCache.put(file, icon);
// Submit a new task to load the image and update the icon
executor.submit(new ThumbnailIconLoader(icon, file));
}
return icon;
}
}
}
private class ThumbnailIconLoader implements Runnable {
private final ImageIcon icon;
private final File file;
public ThumbnailIconLoader(ImageIcon i, File f) {
icon = i;
file = f;
}
public void run() {
System.out.println("Loading image: " + file);
// Load and scale the image down, then replace the icon's old image with the new one.
ImageIcon newIcon = new ImageIcon(file.getAbsolutePath());
Image img = newIcon.getImage().getScaledInstance(ICON_SIZE, ICON_SIZE, Image.SCALE_SMOOTH);
icon.setImage(img);
// Repaint the dialog so we see the new icon.
SwingUtilities.invokeLater(new Runnable() {public void run() {repaint();}});
}
}
}
Known issues:
1) We don't maintain the image's aspect ratio when scaling. Doing so could result in icons with strange dimensions that will break the alignment of the list view. The solution is probably to create a new BufferedImage that is 16x16 and render the scaled image on top of it, centered. You can implement that if you wish!
2) If a file is not an image, or is corrupted, no icon will be shown at all. It looks like the program only detects this error while rendering the image, not when we load or scale it, so we can't detect this in advance. However, we might detect it if we fix issue 1.
Use fileDialog instead of JfileChooser for choising the image:
FileDialog fd = new FileDialog(frame, "Test", FileDialog.LOAD);
String Image_path
fd.setVisible(true);
name = fd.getDirectory() + fd.getFile();
image_path=name;
ImageIcon icon= new ImageIcon(name);
icon.setImage(icon.getImage().getScaledInstance(jLabel2.getWidth(),jLabel2.getHeight() , Image.SCALE_DEFAULT));
jLabel2.setIcon(icon);
You could use a default icon for each fileand load the actual icons in another thread (perhaps using a SwingWorker?). As the icons are loaded the SwingWorker could call back and update the FileView.
Not sure if a single SwingWorker would do the trick, or whether it would be better to use one for each icon being loaded.

Categories

Resources