2010-11-04 18 views
6

मैं छवि फ़ाइलों के थंबनेल दृश्य के साथ JFileChooser बनाना चाहता था। इसलिए मैंने फ़ाइल दृश्य को उपclassed और विधि में ImageIcon बनाया है जो कुछ स्केलिंग सोथैट थंबनेल छवियां दिखाए गए हैं।jfilechooser दिखाएं छवि थंबनेल

हालांकि, समग्र प्रभाव यह है कि, filechooser विजेट निर्देशिका खोलने और थंबनेल दिखाने से पहले कुछ समय लेता है .. नीचे छवि Icon() बनाने के लिए, मुझे छवि Imagepath() के साथ दो बार एक बार नया ImageIcon() कॉल करने की आवश्यकता है आकार बदलने वाले छवि के साथ कन्स्ट्रक्टर तर्क के रूप में। मुझे लगता है कि यह वही है जो विजेट को धीमा करता है।

क्या कोई और अधिक कुशल विकल्प है? कोई भी सुझाव/पॉइंटर्स का स्वागत है।

धन्यवाद, निशान

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 
} 

उत्तर

7

मैं वास्तव में यह देखकर आश्चर्यचकित था कि, मूल रूप से & विंडोज़ में महसूस करने के बावजूद, फाइल चयनकर्ता के पास वास्तव में थंबनेल दृश्य नहीं है। मैंने आपके उदाहरण की कोशिश की और आप सही लाइनों के साथ जा रहे हैं, लेकिन मुझे लगता है कि यह बड़ी छवियों के साथ फ़ोल्डरों के लिए कितनी धीमी थी। ओवरहेड निश्चित रूप से, फ़ाइल सामग्री को पढ़ने के दौरान I/O के कारण होता है और फिर छवि को व्याख्या करता है, जो अपरिहार्य है। फ़ाइल सूची में दिखाया गया है से पहले, जब आप एक आइकन पर माउस, और जब चयन परिवर्तन -

क्या और भी बदतर है, कि मुझे पता चला है कि FileView.getIcon(File) एक बहुत कहा जाता है। अगर हम उन्हें लोड करने के बाद छवियों को कैश नहीं करते हैं, तो हम हर समय छवियों को फिर से लोड कर देंगे।

स्पष्ट समाधान सभी छवि लोडिंग को किसी अन्य थ्रेड या थ्रेड पूल पर धक्का देना है, और एक बार हमारे स्केल किए गए परिणाम के बाद, इसे अस्थायी कैश में डाल दें ताकि इसे फिर से पुनर्प्राप्त किया जा सके।

मैं Image और ImageIcon बहुत से आसपास खेला और मुझे पता चला कि एक ImageIcon की छवि setImage(Image) फोन करके किसी भी समय बदला जा सकता है। हमारे लिए इसका क्या अर्थ है, getIcon(File) के भीतर, हम तुरंत रिक्त या डिफ़ॉल्ट आइकन वापस कर सकते हैं, लेकिन इसके संदर्भ में रहें, इसे एक कार्यकर्ता थ्रेड के साथ पास कर दें जो पृष्ठभूमि में छवि को लोड करेगा और बाद में आइकन की छवि सेट करेगा किया गया (केवल एक ही पकड़ यह है कि हमें परिवर्तन देखने के लिए repaint() पर कॉल करना होगा)।

इस उदाहरण के लिए, मैं एक ExecutorService कैश्ड थ्रेड पूल (यह सबसे तेज़ तरीका सभी छवियों को प्राप्त करने के लिए है, लेकिन मैं/हे का एक बहुत का उपयोग करता है) छवि लोड कार्यों पर कार्रवाई करने के उपयोग कर रहा हूँ। मैं कैश के रूप में WeakHashMap का भी उपयोग कर रहा हूं, यह सुनिश्चित करने के लिए कि हम केवल तब तक कैश किए गए आइकन पर रखें जब तक हमें उनकी आवश्यकता हो। आप किसी अन्य प्रकार के मानचित्र का उपयोग कर सकते हैं, लेकिन स्मृति से बाहर निकलने से बचने के लिए आपको अपने द्वारा बनाए गए आइकन की संख्या प्रबंधित करना होगा।

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

} 

ज्ञात मुद्दे:

1) हम जब स्केलिंग छवि के पक्ष अनुपात को बनाए रखने नहीं है। ऐसा करने से अजीब आयाम वाले आइकन हो सकते हैं जो सूची दृश्य के संरेखण को तोड़ देंगे।समाधान शायद एक नया BufferedImage बनाने के लिए है जो कि 16x16 है और इसके शीर्ष पर स्केल की गई छवि को प्रस्तुत करें। यदि आप चाहें तो आप इसे लागू कर सकते हैं!

2) यदि कोई फ़ाइल कोई छवि नहीं है, या दूषित है, तो कोई आइकन बिल्कुल नहीं दिखाया जाएगा। ऐसा लगता है कि प्रोग्राम केवल छवि को प्रतिपादित करते समय इस त्रुटि का पता लगाता है, न कि जब हम इसे लोड या स्केल करते हैं, तो हम इसे पहले से नहीं पहचान सकते हैं। हालांकि, हम यह पता लगा सकता है अगर हम छवि choising के लिए मुद्दा 1.

0

आप प्रत्येक के लिए एक डिफ़ॉल्ट आइकन का उपयोग fileand एक और धागा में वास्तविक प्रतीक लोड कर सके (शायद एक SwingWorker का उपयोग कर?)। जैसे-जैसे आइकन लोड होते हैं, स्विंगवर्कर वापस कॉल कर सकता है और FileView को अपडेट कर सकता है।

सुनिश्चित नहीं है कि एक स्विंगवर्कर चाल करेगा या फिर प्रत्येक आइकन लोड होने के लिए एक का उपयोग करना बेहतर होगा या नहीं।

4

उपयोग fileDialog बजाय JfileChooser तय:

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

2012 में एक स्विंग प्रश्न में AWT सुझाव? Eww ... –

संबंधित मुद्दे