2010-11-04 15 views
6

Chciałem stworzyć JFileChooser z widoku miniatur plików graficznych.Także I podkategorii FileView i w metodzie, która tworzy ImageIcon zrobił niektóre skalowanie sothat miniatury są wyświetlane.Dokonywanie jfilechooser Pokaż miniatury obrazów

Jednak ogólny efekt polega na tym, że widżet filechooser potrzebuje trochę czasu, aby otworzyć katalog i wyświetlić miniatury. W poniższym przykładzie createImageIcon() muszę wywołać dwa razy nowe ImageIcon() z obrazkiem ścieżki do pliku i następną ze zmienionym obrazem jako argumentem konstruktora. Myślę, że to właśnie spowalnia widżet.

Czy istnieje bardziej skuteczna alternatywa? Wszelkie sugestie/wskaźniki są najbardziej mile widziane.

Dzięki, znak

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 
} 

Odpowiedz

7

Byłem naprawdę zaskoczony, widząc, że pomimo tego, że w Windowsie czuć się jak w oryginalnym stylu, wybieracz plików rzeczywiście nie ma widoku miniatur. Próbowałem twojego przykładu i idziesz właściwą linią, ale widzę, jak powolne było dla folderów z dużą ilością dużych obrazów. Narzut jest oczywiście spowodowany przez wejścia/wyjścia podczas czytania zawartości pliku, a następnie interpretacji obrazu, który jest nieunikniony.

Co gorsza, dowiedziałem się, że FileView.getIcon(File) nazywa się lot - przed wyświetleniem listy plików, po najechaniu myszą na ikonę i zmianie wyboru. Jeśli nie będziemy buforować obrazów po ich załadowaniu, będziemy bezsensownie przeładowywać obrazy przez cały czas.

Oczywistym rozwiązaniem jest wypchnięcie całego obrazu załadowanego na inny wątek lub pulę wątków, a po uzyskaniu wyniku zmniejszonego, umieść go w tymczasowej pamięci podręcznej, aby można ją było odzyskać ponownie.

Bardzo często bawiłem się z Image i ImageIcon i odkryłem, że obraz ImageIcon można zmienić w dowolnym momencie, dzwoniąc pod numer setImage(Image). Dla nas oznacza to, że w ciągu getIcon(File) możemy natychmiast zwrócić pustą lub domyślną ikonę, ale zachować odniesienie do niej, przekazując ją do wątku roboczego, który załaduje obraz w tle i ustawić obraz ikony później, gdy jest done (Jedynym haczykiem jest to, że musimy zadzwonić pod numer repaint(), żeby zobaczyć zmianę).

Dla tego przykładu używam buforowanej puli wątków ExecutorService (jest to najszybszy sposób na uzyskanie wszystkich obrazów, ale wymaga dużej liczby operacji we/wy) w celu przetworzenia zadań ładowania obrazów. Używam też jako pamięci podręcznej WeakHashMap, aby zapewnić, że trzymamy się tylko buforowanych ikon tak długo, jak ich potrzebujemy. Możesz użyć innego rodzaju mapy, ale będziesz musiał zarządzać liczbą trzymanych ikon, aby uniknąć wyczerpania pamięci.

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();}}); 
     } 
    } 

} 

Znane problemy:

1) Nie utrzymać współczynnik kształtu obrazu podczas skalowania. Może to spowodować ikony o dziwnych wymiarach, które przerywają wyrównanie widoku listy.Rozwiązaniem jest prawdopodobnie utworzenie nowego BufferedImage o wymiarach 16x16 i wyśrodkowanie na nim skalowanego obrazu. Możesz to zrealizować, jeśli chcesz!

2) Jeśli plik nie jest obrazem lub jest uszkodzony, żadna ikona nie będzie widoczna. Wygląda na to, że program wykrywa tylko ten błąd podczas renderowania obrazu, a nie kiedy go ładujemy lub skalujemy, więc nie możemy tego wcześniej wykryć. Jednak możemy wykryć, jeśli mamy rozwiązać problem 1.

0

Można użyć domyślną ikonę dla każdego fileand załadować rzeczywistych ikon w innym wątku (być może przy użyciu SwingWorker?). Po załadowaniu ikon, SwingWorker może oddzwonić i zaktualizować FileView.

Nie jestem pewien, czy pojedynczy SwingWorker mógłby zrobić lewę, czy lepiej byłoby użyć jednej dla każdej ładowanej ikony.

4

Korzystając fileDialog zamiast JfileChooser dla choising obraz:

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); 
+0

sugerując AWT w pytaniu Swing w 2012 roku? Eww ... –