Swing是否支持Windows 7风格的文件选择器?

时间:2011-04-18 13:46:03

标签: java swing filechooser

我刚刚根据JFileChooser entry of the Swing Tutorial向我正在编写的小型桌面应用添加了一个标准的“打开文件”对话框。它正在生成一个如下所示的窗口:

screenshot of unwanted/XP-style window

但我希望有一个看起来像这样的窗口:

screenshot of desired/7-style window

换句话说,我希望我的文件选择器具有Windows Vista / Windows 7的风格,而不是Windows XP的风格。这可能在Swing吗?如果是这样,它是如何完成的? (出于此问题的目的,假设代码将仅在Windows 7计算机上运行。)

10 个答案:

答案 0 :(得分:21)

Java 6中的Swing似乎不支持此功能。

目前,我可以找到打开此对话框的最简单方法是通过SWT,而不是Swing。 SWT的FileDialog(javadoc)显示此对话框。以下是对SWT的FileDialog snippet的修改,以使用open而不是save对话框。我知道这不是您正在寻找的,但您可以将其与实用程序类隔离,并将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 ();
    }
} 

答案 1 :(得分:11)

即使是本机Windows应用程序也可以在Windows 7上显示此类对话框。这通常由OPENFILENAME结构中的标志控制,其大小在调用WinAPI函数GetOpenFileName时传递。 Swing(Java)使用钩子从“打开文件”对话框中获取事件;这些事件在Windows XP和Windows 7版本之间以不同方式传递。

所以答案是你无法从Swing控制FileChooser的外观。但是,当Java获得对这种新外观的支持时,您将自动获得新样式。

另一种选择是使用SWT,如this answer中所述。或者,您可以使用JNA调用Windows API或编写本机方法来执行此操作。

答案 2 :(得分:7)

有点像黑客,而且比Swing版本的权力稍微弱一些,但你考虑过使用java.awt.FileDialog吗?它不应该只是看起来像Windows文件选择器,但实际上一个。

答案 3 :(得分:7)

我不相信Swing会覆盖它,虽然它可能,如果它不是你可能需要看一些像SWT,这将使用实际的本机组件,或做一个自定义UI元素,如某事出自“肮脏的富客户”一书。

答案 4 :(得分:7)

Java 8可能最终会为此提供解决方案,但不幸的是(对于Swing应用程序)它只是作为JavaFX类FileChooser

我已经从here测试了这段代码,它确实弹出了一个现代对话框(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应用中,您必须通过Platform.runLater在javafx主题中运行它(如here所示)。

请注意,这将需要您初始化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);
});

答案 5 :(得分:2)

好问题+1,看起来就像他们“忘记”为Win7(defaultLookAndFeel)实现了一些东西到Java6中,但是对于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() {
    }
}

答案 6 :(得分:1)

虽然不能让这个目录工作!! DirectoryDialog将我们返回到树样式目录选择器,该选择器与问题中列出的选择器相同。问题是它不允许我选择/选择/打开隐藏文件夹。它也不允许导航到AppData,ProgramData等文件夹。

Windows 7样式的filedialog(swt)允许导航到这些文件夹,但是再次,不允许选择文件夹:(

<强>更新 要查看隐藏文件夹,请使用JFileChooser并使用setFileHidingEnabled(false)。唯一的要求是用户需要在

中选择“显示隐藏文件,文件夹和驱动器”
  

文件夹选项 - &gt;图

Windows资源管理器的

您将无法获得地址栏的灵活性,但如果您正在寻找Java中的非树类文件选择器,这也允许您浏览/查看隐藏文件/文件夹 - 那么这应该足够了

答案 7 :(得分:1)

约翰麦卡锡的回答似乎是最好的。这里有一些建议。

import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.graphics.Image;

在左上角添加图片。使用&#34; getResourceAsStream&#34;非常重要,您在导出后会注意到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();

答案 8 :(得分:0)

由于Swing模拟各种L&amp; F,我猜你最好的选择是将你的JRE升级到最新版本,并希望JFileChooser UI已经更新。

答案 9 :(得分:0)

JFileChooser一直看起来有点奇怪,也有点慢。

尝试使用SWT的文件追踪器,或者你可以在JNA中包装C调用。