如何在Java

时间:2017-02-04 00:32:41

标签: java swing singleton jfilechooser

我有一个名为MyFileChooser的单例模式类,根据构造函数参数,如果JFileChooser为FILES_ONLYDIRECTORIES_ONLY则适应。

我希望在JFrame中有JFileChooser,所以我可以在JFileChooser框架的上方和下方添加其他信息,因此结构将会显示:

JFrame
 | JLabel
 | JFileChooser
 | JLabel
// end of JFrame
import javax.swing.JFrame;
import javax.swing.JFileChooser;

public class MyFileChooser {
    private JFrame frame;
    private boolean isFilesOnly;
    private static final MyFileChooser instance_files = new MyFileChooser( true );
    private static final MyFileChooser instance_dirs = new MyFileChooser( false );

    private JFileChooser dynamicChooser;

    private MyFileChooser( boolean filesOnly ) {
        this.frame = new JFrame();
        this.isFilesOnly = filesOnly;
        this.dynamicChooser = new JFileChooser();
        this.frameSetup();
        this.chooserSetup();
    }

    public MyFileChooser getInstance( boolean filesOnly ) {
        if ( filesOnly ) {
            return MyFileChooser.instance_files;
        } else {
            return MyFileChooser.instance_dirs;
        }
    }

    public void frameSetup() {
        // jframe and labels setup code
        this.frame.getContentPane().add( this.dynamicChooser );
    }

    public void chooserSetup() {
        if ( this.isFilesOnly ) {
            this.dynamicChooser.setFileSelectionMode( JFileChooser.FILES_ONLY );
        } else {
            this.dynamicChooser.setFileSelectionMode( JFileChooser.DIRECTORIES_ONLY );
        }
        this.dynamicChooser.setMultiSelectionEnabled(true);
        this.dynamicChooser.setDialogType(JFileChooser.CUSTOM_DIALOG);
    }

问题是我不知道如何为JFileChooser的“关闭”和“打开”按钮附加处理程序。我发现的唯一一件事是:

public void handleSelectedFiles() {
   int returnVal = this.dynamicChooser.showDialog(this.frame, "Open");
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            File[] files = this.dynamicChooser.getSelectedFiles();
            // do something
        }
}

但是,如果调用此方法,它会打开两个实例,即使没有JFrame wrap& JLabels来自所需的结构。 所以我的问题是如何从JFileChooser获取“打开”和“关闭”按钮以附加处理程序(实例不同)或如何通过其他方式处理所选文件。

1 个答案:

答案 0 :(得分:3)

你的第一个问题就在这里

int returnVal = this.dynamicChooser.showDialog(this.frame, "Open");

它会调用基础JFileChooser的{​​{1}}方法,因此它会构建自己的窗口,忽略你的窗口

更好的解决方案是按需创建showDialog并使用它来容纳文件选择器和其他控件

更像是......

JDialog

目的是模仿来自public class MyFileChooser { private final boolean isFilesOnly; private static final MyFileChooser INSTANCE_FILES = new MyFileChooser(true); private static final MyFileChooser INSTANCE_DIRS = new MyFileChooser(false); private final JFileChooser dynamicChooser; private MyFileChooser(boolean filesOnly) { this.isFilesOnly = filesOnly; this.dynamicChooser = new JFileChooser(); dynamicChooser.setControlButtonsAreShown(false); this.chooserSetup(); } public MyFileChooser getInstance(boolean filesOnly) { if (filesOnly) { return MyFileChooser.INSTANCE_FILES; } else { return MyFileChooser.INSTANCE_DIRS; } } public void frameSetup(Container parent) { // jframe setup code parent.add(this.dynamicChooser); } public void chooserSetup() { if (this.isFilesOnly) { this.dynamicChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); } else { this.dynamicChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); } this.dynamicChooser.setMultiSelectionEnabled(true); this.dynamicChooser.setDialogType(JFileChooser.CUSTOM_DIALOG); } public File[] showOpenDialog(Component parent, String title) { JDialog dialog = new JDialog(parent == null ? null : SwingUtilities.getWindowAncestor(parent), title); dialog.setModal(true); frameSetup(dialog); dialog.pack(); dialog.setLocationRelativeTo(parent); dialog.setVisible(true); return dynamicChooser.getSelectedFiles(); } } 的{​​{1}}的行为。在这个例子中,我隐藏了"正常"控制按钮,因为我假设您将提供自己的控制按钮,您可以通过它来更改返回文件

现在,如果您仍想使用标准按钮控件,则可以将showDialog附加到JFileChooser

ActionListener

当我测试时,取消按钮返回JFileChooser并选择按钮返回dynamicChooser.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { String cmd = e.getActionCommand(); //... } });

现在,因为我的示例使用了动态对话框,您可能需要创建一个可以控制对话框的动态CancelSelection,因为您不想继续将ApproveSelection添加到ActionListener没有移除它们,类似......

ActionListener

作为例子

观察

因为我知道如果我不这样做,有人会劝我遏制......

Sington的Java是棘手的事情,关于这个问题有无数的线索,然而,人们普遍认为最好的方法(现在)是使用FileChooser,这解决了旧的所有同步问题

所以,相反,您可以考虑使用类似的东西。

public File[] showOpenDialog(Component parent, String title) {
    JDialog dialog = new JDialog(parent == null ? null : SwingUtilities.getWindowAncestor(parent), title);
    dialog.setModal(true);
    frameSetup(dialog);

    ActionListener listener = new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            String cmd = e.getActionCommand();
            //..
            dialog.dispose();
        }
    };
    dynamicChooser.addActionListener(listener);

    dialog.pack();
    dialog.setLocationRelativeTo(parent);

    dialog.setVisible(true);
    dynamicChooser.removeActionListener(listener);

    return dynamicChooser.getSelectedFiles();
}

你可以简单地使用像...这样的东西来打电话。

enum

"我已经提到我希望选择器之间有JLabel,"

我原以为发表评论只是阅读成千上万的例子中的任何一个,显然我错了

因此,public static enum MyFileChooser { INSTANCE_FILES(true), INSTANCE_DIRS(false); private final boolean isFilesOnly; private final JFileChooser dynamicChooser; private MyFileChooser(boolean filesOnly) { this.isFilesOnly = filesOnly; this.dynamicChooser = new JFileChooser(); //dynamicChooser.setControlButtonsAreShown(false); this.chooserSetup(); } public void frameSetup(Container parent) { // jframe setup code parent.add(this.dynamicChooser); } public void chooserSetup() { if (this.isFilesOnly) { this.dynamicChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); } else { this.dynamicChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); } this.dynamicChooser.setMultiSelectionEnabled(true); this.dynamicChooser.setDialogType(JFileChooser.CUSTOM_DIALOG); } public File[] showOpenDialog(Component parent, String title) { JDialog dialog = new JDialog(parent == null ? (JDialog)null : SwingUtilities.getWindowAncestor(parent), title); dialog.setModal(true); frameSetup(dialog); ActionListener listener = new ActionListener() { @Override public void actionPerformed(ActionEvent e) { String cmd = e.getActionCommand(); //.. dialog.dispose(); } }; dynamicChooser.addActionListener(listener); dialog.pack(); dialog.setLocationRelativeTo(parent); dialog.setVisible(true); dynamicChooser.removeActionListener(listener); return dynamicChooser.getSelectedFiles(); } } 方法的简单更新解决了这个问题......

File[] files = MyFileChooser.INSTANCE_FILES.showOpenDialog(null, "Open");

Simple Layout

有关详细信息,请查看How to Use BorderLayout

为确保其正常运行,我更新了frameSetup方法以使用

public void frameSetup(Container parent) {
    // jframe setup code
    parent.setLayout(new BorderLayout());
    parent.add(new JLabel("I'm on top"), BorderLayout.NORTH);
    parent.add(this.dynamicChooser);
    parent.add(new JLabel("I'm on bottom"), BorderLayout.SOUTH);
}

而不仅仅是传递showOpenDialog的实例,这可以确保我们正在影响正确的容器