带有图标和文件名的JavaFX文件列表视图

时间:2015-01-19 22:15:02

标签: javafx

在JavaFX对话框中,我想显示一个包含图标和文件名的文件列表。

很容易找到如何获取文件扩展名的图标:

File file = File.createTempFile("icon", ".doc");  
FileSystemView view = FileSystemView.getFileSystemView();      
java.swing.Icon icon = view.getSystemIcon(file);      
file.delete();

但是,如何在JavaFX Swing Icon中绘制ListView

private static class AttachmentListCell extends ListCell<String> {
    @Override
    public void updateItem(String fileName, boolean empty) {
        if (item != null) {

            // Get file Icon for fileName as shown above.
            java.swing.Icon icon = 

            // Transform Icon to something that can be 
            // added to the box, maybe an ImageView.
            javafx.scene.image.ImageView image = ???

            // Label for file name
            Label label = new Label(item);

            HBox box = new HBox();
            box.getChildren().addAll(image, label);
            setGraphic(box);
        }
    }
}

2 个答案:

答案 0 :(得分:6)

我提出了这个代码,它似乎可以将getSystemIcon返回的图标转换为JavaFX可以理解的格式。它通过使用SwingUtilities.invokeLaterPlatform.runLater的组合来尝试减轻两个项目之间的任何潜在线程问题。 javax.swing.Icon被绘制为java.awt.BufferedImage,由SwingFXUtils转换为JavaFX图像。

所以Swing Icon =&gt;您询问的代码的JavaFX图像部分似乎有效。唯一的事情是,当我在运行Oracle Java8u20的OS X 10.7上测试应用程序时,我尝试的每个文件扩展名类型都给出了完全相同的图标。所以看起来你通过swing FileSystemView从系统获取图标的方法在OS X上确实不受支持(据我所知)。我想你可以在另一个操作系统上尝试它,看看它是否适合你(假设你的任务不需要在OS X上支持这个图标查找功能)。

所以谷歌搜索引出了以下问题:

在这方面,Sam Barnum建议FileViewFileSystemView好得多 - 所以它对我有用。我将代码切换为使用FileView,之后开始在OS X上为不同的文件类型获取不同的图标。图标仍然是非常小的16x16图标(我不知道如何检索高分辨率例如视网膜图标),但至少检索到的图标显示正确且文件类型特定。

import javafx.application.Application;
import javafx.application.Platform;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

public class FileIconViewer extends Application {

    @Override
    public void start(Stage stage) throws IOException {
        Runnable fetchIcon = () -> {
            File file = null;
            try {
                file = File.createTempFile("icon", ".png");

                // commented code always returns the same icon on OS X...
                // FileSystemView view = FileSystemView.getFileSystemView();
                // javax.swing.Icon icon = view.getSystemIcon(file);

                // following code returns different icons for different types on OS X...
                final javax.swing.JFileChooser fc = new javax.swing.JFileChooser();
                javax.swing.Icon icon = fc.getUI().getFileView(fc).getIcon(file);

                BufferedImage bufferedImage = new BufferedImage(
                    icon.getIconWidth(), 
                    icon.getIconHeight(), 
                    BufferedImage.TYPE_INT_ARGB
                );
                icon.paintIcon(null, bufferedImage.getGraphics(), 0, 0);

                Platform.runLater(() -> {
                    Image fxImage = SwingFXUtils.toFXImage(
                        bufferedImage, null
                    );
                    ImageView imageView = new ImageView(fxImage);
                    stage.setScene(
                        new Scene(
                            new StackPane(imageView), 
                            200, 200
                        )
                    );
                    stage.show();
                });
            } catch (IOException e) {
                e.printStackTrace();
                Platform.exit();
            } finally {
                if (file != null) {
                    file.delete();
                }
            }
        };

        javax.swing.SwingUtilities.invokeLater(fetchIcon);
    }

    public static void main(String[] args) { launch(args); }
}

注意:JavaFX问题跟踪器中存在将此功能添加到JavaFX的现有请求(它目前尚未安排实施,但您可以登录问题跟踪器并对问题进行投票,对其进行评论,链接它回到这个StackOverflow问题等):

答案 1 :(得分:6)

以下是带有文件图标的列表视图的示例:

enter image description here

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.Scene;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Callback;

import javax.swing.filechooser.FileSystemView;

public class ListViewCellFactory2 extends Application {

    ListView<String> list = new ListView<String>();
    ObservableList<String> data = FXCollections.observableArrayList(
            "a.msg", "a1.msg", "b.txt", "c.pdf", 
            "d.html", "e.png", "f.zip",
            "g.docx", "h.xlsx", "i.pptx");

    @Override
    public void start(Stage stage) {
        VBox box = new VBox();
        Scene scene = new Scene(box, 200, 200);
        stage.setScene(scene);
        stage.setTitle("ListViewSample");
        box.getChildren().addAll(list);
        VBox.setVgrow(list, Priority.ALWAYS);

        list.setItems(data);

        list.setCellFactory(new Callback<ListView<String>, ListCell<String>>() {
            @Override
            public ListCell<String> call(ListView<String> list) {
                return new AttachmentListCell();
            }
        });

        stage.show();
    }

    private static class AttachmentListCell extends ListCell<String> {
        @Override
        public void updateItem(String item, boolean empty) {
            super.updateItem(item, empty);
            if (empty) {
                setGraphic(null);
                setText(null);
            } else {
                Image fxImage = getFileIcon(item);
                ImageView imageView = new ImageView(fxImage);
                setGraphic(imageView);
                setText(item);
            }
        }
    }

    public static void main(String[] args) {
        launch(args);
    }


    static HashMap<String, Image> mapOfFileExtToSmallIcon = new HashMap<String, Image>();

    private static String getFileExt(String fname) {
        String ext = ".";
        int p = fname.lastIndexOf('.');
        if (p >= 0) {
            ext = fname.substring(p);
        }
        return ext.toLowerCase();
    }

    private static javax.swing.Icon getJSwingIconFromFileSystem(File file) {

        // Windows {
        FileSystemView view = FileSystemView.getFileSystemView();
        javax.swing.Icon icon = view.getSystemIcon(file);
        // }

        // OS X {
        //final javax.swing.JFileChooser fc = new javax.swing.JFileChooser();
        //javax.swing.Icon icon = fc.getUI().getFileView(fc).getIcon(file);
        // }

        return icon;
    }

    private static Image getFileIcon(String fname) {
        final String ext = getFileExt(fname);

        Image fileIcon = mapOfFileExtToSmallIcon.get(ext);
        if (fileIcon == null) {

            javax.swing.Icon jswingIcon = null; 

            File file = new File(fname);
            if (file.exists()) {
                jswingIcon = getJSwingIconFromFileSystem(file);
            }
            else {
                File tempFile = null;
                try {
                    tempFile = File.createTempFile("icon", ext);
                    jswingIcon = getJSwingIconFromFileSystem(tempFile);
                }
                catch (IOException ignored) {
                    // Cannot create temporary file. 
                }
                finally {
                    if (tempFile != null) tempFile.delete();
                }
            }

            if (jswingIcon != null) {
                fileIcon = jswingIconToImage(jswingIcon);
                mapOfFileExtToSmallIcon.put(ext, fileIcon);
            }
        }

        return fileIcon;
    }

    private static Image jswingIconToImage(javax.swing.Icon jswingIcon) {
        BufferedImage bufferedImage = new BufferedImage(jswingIcon.getIconWidth(), jswingIcon.getIconHeight(),
                BufferedImage.TYPE_INT_ARGB);
        jswingIcon.paintIcon(null, bufferedImage.getGraphics(), 0, 0);
        return SwingFXUtils.toFXImage(bufferedImage, null);
    }

}

编辑:在HDPI监视器上,文件图标被剪裁。

enter image description here

  1. 要使图标完全显示在行中需要做些什么?
  2. 如何从Java中检索比例因子?