根据Swing Tutorial的条目,我刚刚在我正在编写的一个小型桌面应用程序中添加了一个标准的“打开文件”对话框。它正在生成一个如下所示的窗口:JFileChooser
但我希望有一个看起来像这样的窗口:
换句话说,我希望我的文件选择器具有 Windows Vista/Windows 7 的风格,而不是 Windows XP 的风格。这在 Swing 中可能吗?如果是这样,它是如何完成的?(就本问题而言,假设代码将仅在 Windows 7 计算机上运行。)
根据Swing Tutorial的条目,我刚刚在我正在编写的一个小型桌面应用程序中添加了一个标准的“打开文件”对话框。它正在生成一个如下所示的窗口:JFileChooser
但我希望有一个看起来像这样的窗口:
换句话说,我希望我的文件选择器具有 Windows Vista/Windows 7 的风格,而不是 Windows XP 的风格。这在 Swing 中可能吗?如果是这样,它是如何完成的?(就本问题而言,假设代码将仅在 Windows 7 计算机上运行。)
Java 6 中的 Swing 似乎不支持这一点。
目前,我能找到打开此对话框的最简单方法是通过 SWT,而不是 Swing。SWT 的 FileDialog ( javadoc ) 会弹出这个对话框。以下是对 SWT 的FileDialog 片段的修改,以使用打开而不是保存对话框。我知道这不是您正在寻找的,但是您可以将其隔离到一个实用程序类中,并将 swt.jar 添加到您的类路径中以实现此功能。
import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
public class SWTFileOpenSnippet {
public static void main (String [] args) {
Display display = new Display ();
Shell shell = new Shell (display);
// Don't show the shell.
//shell.open ();
FileDialog dialog = new FileDialog (shell, SWT.OPEN | SWT.MULTI);
String [] filterNames = new String [] {"All Files (*)"};
String [] filterExtensions = new String [] {"*"};
String filterPath = "c:\\";
dialog.setFilterNames (filterNames);
dialog.setFilterExtensions (filterExtensions);
dialog.setFilterPath (filterPath);
dialog.open();
System.out.println ("Selected files: ");
String[] selectedFileNames = dialog.getFileNames();
for(String fileName : selectedFileNames) {
System.out.println(" " + fileName);
}
shell.close();
while (!shell.isDisposed ()) {
if (!display.readAndDispatch ()) display.sleep ();
}
display.dispose ();
}
}
甚至本机 Windows 应用程序也可以在 Windows 7 上显示这种类型的对话框。这通常由OPENFILENAME
结构中的标志及其大小控制在对 WinAPI 函数的调用中GetOpenFileName
。Swing (Java) 使用钩子从 Open File 对话框中获取事件;这些事件在 Windows XP 和 Windows 7 版本之间的传递方式不同。
所以答案是你无法从 Swing 控制 FileChooser 的外观。但是,当 Java 获得对这种新外观的支持时,您将自动获得新样式。
另一种选择是使用 SWT,如this answer中所建议的那样。或者,您可以使用 JNA 调用 Windows API 或编写本机方法来执行此操作。
Java 8 最终可能会为此带来解决方案,但不幸的是(对于 Swing 应用程序)它仅作为 JavaFX 类FileChooser出现:
我已经从这里测试了这段代码,它确实弹出了一个现代对话框(这里是 Windows 7):
FileChooser fileChooser = new FileChooser();
//Set extension filter
FileChooser.ExtensionFilter extFilterJPG = new FileChooser.ExtensionFilter("JPG files (*.jpg)", "*.JPG");
FileChooser.ExtensionFilter extFilterPNG = new FileChooser.ExtensionFilter("PNG files (*.png)", "*.PNG");
fileChooser.getExtensionFilters().addAll(extFilterJPG, extFilterPNG);
//Show open file dialog
File file = fileChooser.showOpenDialog(null);
要将其集成到 Swing 应用程序中,您必须在 javafx 线程中运行它Platform.runLater
(如此处所示)。
请注意,这将需要您初始化 javafx 线程(在示例中,这是在场景初始化时完成的,在 中new JFXPanel()
)。
总而言之,在 Swing 应用程序中准备运行的解决方案如下所示:
new JFXPanel(); // used for initializing javafx thread (ideally called once)
Platform.runLater(() -> {
FileChooser fileChooser = new FileChooser();
//Set extension filter
FileChooser.ExtensionFilter extFilterJPG = new FileChooser.ExtensionFilter("JPG files (*.jpg)", "*.JPG");
FileChooser.ExtensionFilter extFilterPNG = new FileChooser.ExtensionFilter("PNG files (*.png)", "*.PNG");
fileChooser.getExtensionFilters().addAll(extFilterJPG, extFilterPNG);
//Show open file dialog
File file = fileChooser.showOpenDialog(null);
});
有点 hack,并且比 Swing 版本稍微弱一点,但是你考虑过使用java.awt.FileDialog
? 它不应该只是看起来像 Windows 文件选择器,而实际上应该是其中之一。
我不相信 Swing 会涵盖这一点,尽管它可能会涵盖,如果不是,您可能需要查看类似 SWT 之类的东西,它会利用实际的本机组件,或者做一个自定义 UI 元素,比如在《肮脏的富客户》一书。
好问题+1,看起来他们“忘记”在Java6中为Win7(defaultLookAndFeel)实现一些东西,但是对于WinXP来说,工作正确,我也希望,必须存在一些方法/属性
无论如何,您可以使用此代码进行尝试,
import java.io.File;
import javax.swing.*;
import javax.swing.filechooser.FileFilter;
class ChooserFilterTest {
public static void main(String[] args) {
Runnable r = new Runnable() {
@Override
public void run() {
String[] properties = {"os.name", "java.version", "java.vm.version", "java.vendor"};
for (String property : properties) {
System.out.println(property + ": " + System.getProperty(property));
}
JFileChooser jfc = new JFileChooser();
jfc.showOpenDialog(null);
jfc.addChoosableFileFilter(new FileFilter() {
@Override
public boolean accept(File f) {
return f.isDirectory() || f.getName().toLowerCase().endsWith(".obj");
}
@Override
public String getDescription() {
return "Wavefront OBJ (*.obj)";
}
@Override
public String toString() {
return getDescription();
}
});
int result = JOptionPane.showConfirmDialog(null, "Description was 'All Files'?");
System.out.println("Displayed description (Metal): " + (result == JOptionPane.YES_OPTION));
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
SwingUtilities.updateComponentTreeUI(jfc);
} catch (Exception e) {
e.printStackTrace();
}
jfc.showOpenDialog(null);
result = JOptionPane.showConfirmDialog(null, "Description was 'All Files'?");
System.out.println("Displayed description (System): " + (result == JOptionPane.YES_OPTION));
}
};
SwingUtilities.invokeLater(r);
}
private ChooserFilterTest() {
}
}
虽然不能使这个工作目录!DirectoryDialog 让我们回到与问题中列出的相同的树样式目录选择器。问题是它不允许我选择/选择/打开隐藏文件夹。它也不允许导航到 AppData、ProgramData 等文件夹。
Windows 7 风格的文件对话框 (swt) 确实允许导航到这些文件夹,但话又说回来,不允许选择文件夹:(
更新
要查看隐藏文件夹,请使用 JFileChooser 并拥有setFileHidingEnabled(false)
. 唯一的要求是用户需要在
文件夹选项 -> 查看
Windows 资源管理器
您不会获得地址栏的灵活性,但如果您正在寻找 Java 中的非树状文件选择器,它还可以让您浏览/查看隐藏文件/文件夹 - 那么这就足够了
约翰麦卡锡的回答似乎是最好的。这里有一些建议。
import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.graphics.Image;
在左上角添加图像。使用“getResourceAsStream”很重要,导出为 Runnable jar 后您会注意到:
Display display = new Display();
Shell shell = new Shell(display);
InputStream inputImage = getClass().getResourceAsStream("/app/launcher.png");
if (inputImage != null) {
shell.setImage(new Image(display, inputImage));
}
用户的主目录:
String filterPath = System.getProperty("user.home");
获取绝对路径名而不是依赖于过滤器的路径名,这在其他驱动器上是错误的。
String absolutePath = dialog.open();
由于 Swing 模拟各种 L&F,我想您最好的选择是将您的 JRE 升级到最新版本,并希望 JFileChooser UI 已经更新。
JFileChooser 在 Swing 上看起来总是有点奇怪,也有点慢。
尝试使用 SWT 的文件选择器,或者您可以将 C 调用包装在 JNA 中。