在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);
}
}
}
答案 0 :(得分:6)
我提出了这个代码,它似乎可以将getSystemIcon
返回的图标转换为JavaFX可以理解的格式。它通过使用SwingUtilities.invokeLater
和Platform.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建议FileView
比FileSystemView
好得多 - 所以它对我有用。我将代码切换为使用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)
以下是带有文件图标的列表视图的示例:
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监视器上,文件图标被剪裁。