JfileChooser abrindo Imagem em Thumbnail com performance

1 resposta
B
package br.com.B.component.filechooser;

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.filechooser.FileView;
	
	public class BJFileChooser extends JFileChooser {

		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;

		/** All preview icons will be this width and height */
		private static int ICON_SIZE = 60;

		/** 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<File, ImageIcon> imageCache = new WeakHashMap<File, ImageIcon>();

		public BJFileChooser() {
			super();
			setFileView(new ThumbnailView());
		}
		
		public void setIconSize(int size) {
			ICON_SIZE = size;
		}

		private class ThumbnailView extends FileView {
			/** This thread pool is where the thumbnail icon loaders run */
			private final ExecutorService executor = Executors.newCachedThreadPool();

			public String getName(File file){
				String name = file.getName();
				if("".equals(name)){
					return "/";
				}
				else{
					String substring = "";
					String extensao = "";
					
					if(name.length() > 25 && (name.contains("jpg") || name.contains("gif") || name.contains("png"))){
						substring = name.substring(0, 25);
					}
					
					if(substring.equals("")){
						return name;
					}else{
						extensao = name.substring(name.lastIndexOf("."), name.length());  
						return substring + extensao;
					}
				}
			}
			
			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 = (ImageIcon) 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() {
					// 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();

					// calc dimension
					int width = img.getWidth(null);
					int height = img.getHeight(null);

					int newWidth;
					int newHeight;
					double factor;

					if(width > height){
						factor = (double)height/width;
						newWidth = ICON_SIZE;
						newHeight = (int)(ICON_SIZE*factor);
					}
					else{
						factor = (double)width/height;
						newHeight = ICON_SIZE;
						newWidth = (int)(ICON_SIZE*factor);
					}

					img = img.getScaledInstance(newWidth, newHeight, Image.SCALE_SMOOTH);
					icon.setImage(img);

					// Repaint the dialog so we see the new icon.
					SwingUtilities.invokeLater(new Runnable() {public void run() {repaint();}});

				}
			}
		}

Quando abro uma pasta com muitas imagens ocorre Java heap space..
Como posso ter performance com isso?
Como pego somente os Files que estão na tela e exibo Thumbnail ?
Alguma outra ideia ?

1 Resposta

victorcosta

Usa um FileDialog nativo

Ex: o do AWT (mas não suporta filtros e é antigo, não é o mais novo que o Windows 7 usa, a aparência dele no Linux é uma aberração também)

Outras opções:

http://code.google.com/p/xfiledialog/
Permite usar o FileDialog + recente do Windows, adiciona só uns 200k na aplicação e é super simples de usar


Esse não sei usar, mas deve suportar os FileDialogs nativos do Windows, Mac e Linux

Criado 14 de agosto de 2012
Ultima resposta 14 de ago. de 2012
Respostas 1
Participantes 2