0

I have a TableView that lists files within a given folder. Within the TableView, I have a column that holds a button which opens the file when clicked.

I am trying to get the file's filetype icon to display as that button's graphic. For example, a .xlsx file would display the Microsoft Excel icon and .pdf files show the Adobe PDF icon.

From my research, I understand JavaFX has no native way to get a file's associated icon so I will need to do some heavy-handed Swing conversions.

However, the I cannot figure out how to do so within a CellFactory.

Here is the partial code I have so far, in which I need to add the code to get the file's icon:

colOpenFile.setCellFactory(col -> {
    final javafx.scene.control.Button btnOpen = new Button();
    final ImageView openIcon;

    TableCell<FileResource, FileResource> cell = new TableCell<FileResource, FileResource>() {

        @Override
        protected void updateItem(FileResource item, boolean empty) {
            super.updateItem(item, empty);
            if (empty) {
                setGraphic(null);
                setText(null);
            } else {
                Icon icon = FileSystemView.getFileSystemView().getSystemIcon(new File(cell.getItem().getFilename()));
                setAlignment(Pos.CENTER);
                openIcon = fetchFileIcon(item.getFilename());                   
                openIcon.setFitWidth(16);
                openIcon.setFitHeight(16);
                btnOpen.setGraphic(openIcon);
                setGraphic(btnOpen);
            }
        }
    };
}

I have not finished attempting this implementation because I already know this throws an Exception because cell may not have been initialized.

How do I get the file icon for the FileResource being displayed on that row and assign it to the Button, also in that row?

Thank you!

Zephyr
  • 9,885
  • 4
  • 28
  • 63
  • Possible duplicate of [Java/JavaFX: Set Swing Icon for JavaFX label](https://stackoverflow.com/questions/26192832/java-javafx-set-swing-icon-for-javafx-label) – MMAdams Oct 27 '17 at 15:30
  • What do you mean by "throws an exception because `cell` may not have been initialized?" What exception? Where are you referring to the cell before it might have been initialized? – James_D Oct 27 '17 at 18:56
  • @James_D `Icon icon = FileSystemView.getFileSystemView().getSystemIcon(new File(cell.getItem().getFilename()));` within the `updateItem` method. – Zephyr Oct 27 '17 at 19:42
  • So what's the exception? When does it occur? – James_D Oct 27 '17 at 19:43
  • I'm sorry, it is a compiler error, not an exception. `Error:(392, 103) java: variable cell might not have been initialized` – Zephyr Oct 27 '17 at 19:44

1 Answers1

2

Well, you can grab the Swing Icons by using an instance of JFileChooser. Then, according to this question, Java/JavaFX: Set Swing Icon for JavaFX label, you can use SwingFXUtils to get a JavaFX image.

So you could do something like this:

JFileChooser fileChooser = new JFileChooser();
File file = new File(cell.getItem().getFilename());
ImageIcon icon = (ImageIcon) fileChooser.getIcon(file);
BufferedImage image = (BufferedImage) icon.getImage();
Image fxIcon = SwingFXUtils.toFXImage(image, null);

Edit: Found a different way to get the icons here: How do I get a file's icon in Java? where @camickr suggests using FileSystemView to get the Icon like this:

Icon icon = FileSystemView.getFileSystemView().getSystemIcon( file );

This is probably a better solution, since, as @James_D pointed out, you shouldn't create Swing components outside of the AWT event thread, and this FileSystemView method is static.

MMAdams
  • 1,508
  • 15
  • 29
  • 1
    You should not create the `JFileChooser` on any thread other than the AWT event dispatch thread; that probably won't happen naturally in a JavaFX application. You should probably show how you deal with that (which is a little non-trivial). – James_D Oct 27 '17 at 15:38
  • 1
    @James_D good point, I might add that into my answer later if I find the time. – MMAdams Oct 27 '17 at 15:41
  • I have found many methods of actually getting the icon; my bigger problem is being able to assign it to the button's graphic. The `TableView` lists file objects and I need to get the filename from that object in order to get the icon for the file. However, I cannot figure out how to do this from within the `CellFactory`. – Zephyr Oct 27 '17 at 16:58
  • `new File(cell.getItem().getFilename())` doesn't work? – MMAdams Oct 27 '17 at 17:25
  • @MMAdams I receive this compiler error when trying to refer to `cell`: "Error:(392, 103) java: variable cell might not have been initialized" – Zephyr Oct 27 '17 at 19:45
  • you need to use a cellfactory. see this question. https://stackoverflow.com/questions/10519534/cell-factory-in-javafx – MMAdams Oct 27 '17 at 20:00
  • @MMAdams Thank you for taking the time to respond, but please read my question again. I have already addressed both of your solutions within the original question. I am using a CellFactory already, as shown in the code I posted. – Zephyr Oct 27 '17 at 22:05
  • Your code snippet does not work. `Exception in thread "main" java.lang.ClassCastException: class sun.awt.image.ToolkitImage cannot be cast to class java.awt.image.BufferedImage` – Diarsid Jul 04 '21 at 13:06