2010-11-04 45 views
6

Tôi muốn tạo một JFileChooser với chế độ xem hình thu nhỏ của tệp hình ảnh. Do đó tôi đã phân loại FileView và trong phương thức tạo ra ImageIcon đã làm một số hình ảnh thu nhỏ sothat thu nhỏ được hiển thị.làm jfilechooser hiển thị hình thu nhỏ hình ảnh

Tuy nhiên, hiệu ứng tổng thể là, tiện ích filechooser mất một thời gian trước khi mở thư mục và hiển thị hình thu nhỏ .. Trong createImageIcon() bên dưới, tôi cần gọi mới ImageIcon() hai lần một lần với tệp hình ảnh và tiếp theo với hình ảnh được thay đổi kích thước làm đối số hàm tạo. Tôi nghĩ đây là điều làm chậm tiện ích con.

Có giải pháp thay thế hiệu quả hơn không? Bất kỳ đề xuất/con trỏ nào được chào đón nhiều nhất.

cảm ơn, dấu

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 
} 

Trả lời

7

Tôi thực sự ngạc nhiên khi thấy rằng, mặc dù sử dụng giao diện gốc & cảm thấy trong Windows, trình chọn tệp thực sự không có chế độ xem hình thu nhỏ. Tôi đã thử ví dụ của bạn và bạn đang đi dọc theo dòng bên phải, nhưng tôi thấy tốc độ của các thư mục với rất nhiều hình ảnh lớn. Tất nhiên, phí trên là do I/O khi đọc nội dung tập tin và sau đó giải thích hình ảnh, điều không thể tránh khỏi.

Điều thậm chí còn tệ hơn, là tôi phát hiện ra rằng FileView.getIcon(File) được gọi là - trước khi danh sách tệp được hiển thị, khi bạn di chuột qua biểu tượng và khi lựa chọn thay đổi. Nếu chúng tôi không lưu trữ hình ảnh sau khi tải chúng, chúng tôi sẽ không ngừng tải hình ảnh mọi lúc.

Giải pháp hiển nhiên là đẩy tất cả tải hình ảnh lên một chủ đề khác hoặc một nhóm luồng và sau khi chúng tôi có kết quả thu nhỏ, hãy đưa nó vào bộ đệm tạm thời để có thể truy xuất lại.

Tôi đã chơi xung quanh với ImageImageIcon rất nhiều và tôi phát hiện thấy hình ảnh của ImageIcon có thể được thay đổi bất kỳ lúc nào bằng cách gọi setImage(Image). Điều này có nghĩa là chúng tôi có thể trả lại một biểu tượng trống hoặc mặc định ngay lập tức, nhưng giữ nguyên tham chiếu đến nó, chuyển nó đến chuỗi công nhân sẽ tải hình ảnh ở chế độ nền và đặt hình ảnh của biểu tượng sau khi nó thực hiện (Việc bắt duy nhất là chúng ta phải gọi repaint() để xem thay đổi).

Ví dụ này, tôi đang sử dụng một nhóm hồ sơ lưu trữ ExecutorService được lưu trong bộ nhớ cache (đây là cách nhanh nhất để tải tất cả hình ảnh, nhưng sử dụng nhiều I/O) để xử lý các tác vụ tải hình ảnh. Tôi cũng đang sử dụng WeakHashMap làm bộ nhớ cache, để đảm bảo rằng chúng tôi chỉ giữ các biểu tượng được lưu trong bộ nhớ cache miễn là chúng tôi cần chúng. Bạn có thể sử dụng một loại bản đồ khác, nhưng bạn sẽ phải quản lý số lượng biểu tượng mà bạn nắm giữ, để tránh hết bộ nhớ.

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

} 

vấn đề đã biết:

1) Chúng tôi không duy trì tỷ lệ khía cạnh của hình ảnh khi mở rộng quy mô. Làm như vậy có thể dẫn đến các biểu tượng có kích thước lạ sẽ phá vỡ căn chỉnh của chế độ xem danh sách.Giải pháp có thể là tạo một BufferedImage mới là 16x16 và hiển thị hình ảnh được chia tỷ lệ ở trên cùng của nó, được căn giữa. Bạn có thể thực hiện điều đó nếu bạn muốn!

2) Nếu tệp không phải là hình ảnh hoặc bị hỏng, sẽ không có biểu tượng nào được hiển thị. Có vẻ như chương trình chỉ phát hiện lỗi này trong khi hiển thị hình ảnh, chứ không phải khi chúng tôi tải hoặc chia tỷ lệ hình ảnh, vì vậy chúng tôi không thể phát hiện ra điều này trước. Tuy nhiên, chúng ta có thể phát hiện nó nếu chúng ta khắc phục vấn đề 1.

0

Bạn có thể sử dụng biểu tượng mặc định cho mỗi fileand tải các biểu tượng thực tế trong một thread (có lẽ sử dụng một SwingWorker?). Khi các biểu tượng được nạp, SwingWorker có thể gọi lại và cập nhật FileView.

Không chắc liệu một SwingWorker có thực hiện thủ thuật hay không, hoặc có nên sử dụng mẹo này cho mỗi biểu tượng được tải hay không.

4

Sử dụng fileDialog thay vì JfileChooser cho choising hình ảnh:

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

Đề xuất AWT trong một câu hỏi Swing vào năm 2012? Eww… –

Các vấn đề liên quan