JFileChooser“另存为"复合文档 - 覆盖现有 [英] JFileChooser "Save As" compound document - overwrite existing

查看:46
本文介绍了JFileChooser“另存为"复合文档 - 覆盖现有的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个使用复合文档来存储数据的系统.

I'm working on a system which uses compound documents to store its data.

一切都运行良好 - 我什至有漂亮的图标和双击打开的对话框.

Everything is working beautifully - I even have nice icons and double-click-to-open working on the open dialog.

我的问题是另存为"对话框.如果我保存为尚不存在的复合文档,那么一切都很好.如果我双击一个现有的复合文档,那么我的代码会询问您是否要覆盖它,这也很好.

My problem is with the "Save As" dialog. If I save as a compound document that doesn't already exist then all is fine. If I double-click an existing compound document, then my code asks if you want to overwrite it, and that is also fine.

但是,如果您输入现有复合文档的名称并单击保存",则出现问题的是,它的作用就像您单击取消"一样.

What is working wrong, though, is if you type in the name of an existing compound document and click save, it acts as if you clicked cancel instead.

我使用 FileFilter 和 FileView 来配置文件的所有显示和过滤.

I'm using a FileFilter and a FileView to configure all the display and filtering of the files.

这是我的主要对话框打开功能:

Here's my main dialog opening function:

public void saveAs() {
    JFileChooser fc = new JFileChooser();
    javax.swing.filechooser.FileFilter filter = new SketchFolderFilter();
    fc.setFileFilter(filter);

    javax.swing.filechooser.FileView view = new SketchFileView();
    fc.setFileView(view);

    fc.setCurrentDirectory(Base.getSketchbookFolder());

    int rv = fc.showSaveDialog(this);

    System.err.println("Option: " + rv);
    if (rv == JFileChooser.APPROVE_OPTION) {
        File newFile = fc.getSelectedFile();
        System.err.println("Save As: " + newFile.getAbsolutePath());
        if (newFile.exists()) {
            int n = twoOptionBox(
                JOptionPane.WARNING_MESSAGE,
                "Overwrite File?",
                Translate.w("Do you really want to overwrite the file %1?", 40, "\n", newFile.getName()),
                "Yes", "No");
            if (n != 0) {
                return;
            }
            newFile.delete();
        }
        loadedSketch.saveAs(newFile);
    }
}

这里,如果你需要的话,是我的过滤器和视图类:

And here, if you need it, is my filter and view classes:

public class SketchFileView extends javax.swing.filechooser.FileView {
    public String getTypeDescription(File f) {
        if (Base.isSketchFolder(f)) {
            return Translate.t("UECIDE Sketch Folder");
        }
        return Translate.t("Directory");
    }

    public Boolean isTraversable(File f) {
        if (Base.isSketchFolder(f)) {
            return false;
        }
        return true;
    } 

    public Icon getIcon(File f) {
        if (Base.isSketchFolder(f)) {
            ImageIcon icon = Base.loadIconFromResource("icon16.png");
            return icon;
        }
        return null;
    }
}

public class SketchFolderFilter extends javax.swing.filechooser.FileFilter {
    public boolean accept(File f) {
        if (Base.isSketchFolder(f)) {
            return true;
        }
        if (f.isDirectory()) {
            return true;
        }
        return false;
    }

    public String getDescription() {
        return Translate.t("Sketch Folders");
    }
}

当它工作时,我看到,在标准错误上:

When it works, I see, on stderr:

Option: 0
Save As: /foo/bar/baz

当它不起作用时,我看到:

When it doesn't work I see:

Option: 1

说明:

据我所知,这纯粹是复合文档的问题.

重申场景:

  1. 打开 JFileChooser 将数据保存到复合文档.
  2. 您有一份现有复合文档的列表.
  3. 你双击一个——返回 APPROVE_OPTION 索引,getSelectedFile() 返回 File 对象,或者
  4. 您输入一个不存在的复合文档的名称,然后按保存"或回车键.返回 APPROVE_OPTION 索引,getSelectedFile() 返回 File 对象,但是
  5. 您输入现有复合文档的名称,然后按保存"或回车键.返回CANCEL_OPTION索引,getSelectedFile()返回null,或者
  6. 您按下了取消"按钮.返回 CANCEL_OPTION 索引,getSelectedFile() 返回 null.
  7. 然后您使用带有自己代码的 File 对象来生成复合文档 - 通常删除旧文档(如果它在那里并且用户说他想覆盖)并创建目录并填充它与您的文件.
  1. Open a JFileChooser to save your data to a compound document.
  2. You have a list of existing compound documents.
  3. You double click one - the APPROVE_OPTION index is returned, and getSelectedFile() returns the File object, or
  4. You type the name of a non-existant compound document and press "Save" or the return key. The APPROVE_OPTION index is returned, and getSelectedFile() returns the File object, but
  5. You type the name of an existing compound document and either press "Save" or the return key. The CANCEL_OPTION index is returned, and getSelectedFile() returns null, or
  6. You press the "Cancel" button. The CANCEL_OPTION index is returned, and getSelectedFile() returns null.
  7. You then use the File object with your own code to generate the compound document - typically deleting the old one (if it's there and the user says he wants to overwrite) and making the directory and filling it with your files.

是 5(在我看来)是错误的.它应该返回 APPROVE_OPTION 并且 getSelectedFile() 应该返回一个 File 对象,该对象表示您在 JFileChooser 所在目录中键入的文件(即,与 3 相同).

It's 5 that is (in my opinion anyway) wrong. It should return APPROVE_OPTION and getSelectedFile() should return a File object representing the file you typed in resident in the directory the JFileChooser's in (i.e., the same as 3).

缩小范围.当文件夹不可遍历并且您在选择器中输入其名称并按回车键时,JFileChooser 似乎不喜欢它 - 它试图遍历它但它失败了,并且不知道如何处理它,所以只需将您从返回 0 的 JFileChooser 中删除.这是一个演示它的 SSCCE.在其中包含名为test.X"的文件夹的文件夹上运行此命令并键入test.X".它应该失败.

Narrowing it down. It looks like JFileChooser doesn't like it when a folder is non-traversable and you enter its name into the chooser and hit return - it tries to traverse into it and it fails miserably, and doesn't know what to do with it, so just dumps you out of the JFileChooser returning 0. Here's an SSCCE that demonstrates it. Run this on a folder with a folder within it called "test.X" and type in "test.X". It should fail.

import java.io.*;
import javax.swing.*;


class fctest {

    public class SketchFileView extends javax.swing.filechooser.FileView {
        public Boolean isTraversable(File f) {
            if (f.getName().endsWith(".X")) {
                return false;
            }
            if (f.isDirectory()) {
                return true;
            }
            return true;
        } 
    }

    public class SketchFolderFilter extends javax.swing.filechooser.FileFilter {
        public boolean accept(File f) {
            if (f.getName().endsWith(".X")) {
                return true;
            }
            if (f.isDirectory()) {
                return true;
            }
            return false;
        }

        public String getDescription() {
            return "Sketch Folders";
        }
    }

    public void saveAs() {
        JFileChooser fc = new JFileChooser();
        javax.swing.filechooser.FileFilter filter = new SketchFolderFilter();
        fc.setFileFilter(filter);

        javax.swing.filechooser.FileView view = new SketchFileView();
        fc.setFileView(view);

        fc.setCurrentDirectory(new File("."));

        int rv = fc.showSaveDialog(null);

        System.err.println("Option: " + rv);
        if (rv == JFileChooser.APPROVE_OPTION) {
            File newFile = fc.getSelectedFile();
            System.err.println("Save As: " + newFile.getAbsolutePath());
        }
    }

    public static void main(String[] args) {
        fctest main = new fctest();
        main.saveAs();
    }
}

推荐答案

是如果您输入现有复合文档的名称并单击保存",它的作用就像您单击取消"一样.

is if you type in the name of an existing compound document and click save, it acts as if you clicked cancel instead.

我认为您的意思是文件选择器关闭,但您希望它保持打开状态,以便用户有机会更改文件名.如果是这样,那么您可以覆盖 JFileChooser 的 approveSelection() 方法以显示确认对话框:

I think you mean the file chooser closes, but you would like it to remain open to give the user a chance to change the file name. If so, then you can override the approveSelection() method of the JFileChooser to display the confirm dialog:

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import javax.swing.*;
import javax.swing.plaf.basic.*;

public class FileChooserSave
{
    private static void createAndShowUI()
    {
        final JFileChooser chooser = new JFileChooser( new File(".") )
        {
            public void approveSelection()
            {
                if (getSelectedFile().exists())
                {
                    int n = JOptionPane.showConfirmDialog(
                        this,
                        "Do You Want to Overwrite File?",
                        "Confirm Overwrite",
                        JOptionPane.YES_NO_OPTION);

                    if (n == JOptionPane.YES_OPTION)
                        super.approveSelection();

                }
                else
                    super.approveSelection();
            }
        };

        chooser.setSelectedFile( new File("something.rob") );
        int returnVal = chooser.showSaveDialog(null);

        if(returnVal == JFileChooser.APPROVE_OPTION)
        {
           System.out.println(chooser.getSelectedFile() );
        }
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowUI();
            }
        });
    }
}

我添加了以下内容:

fc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);

它允许您选择直接复合",但您也可以选择一个非复合目录,这是一些进步.

It allowed you to select a "compound directly" but you could also select a non compound directory which was some progress.

然后我覆盖文件选择器的approveSelection"方法以只批准复合目录,现在它似乎工作得相当好?

I then override the "approveSelection" method of the file chooser to only approve compound directories and it now seems to work reasonably well?

必须承认我不知道为什么它会这样做,所以它更像是一种蛮力方法.

Must admit I don't know why it does what it does so its more of a brute force approach.

这是我测试的代码:

import java.io.*;
import javax.swing.*;


class fctest {

    public class SketchFileView extends javax.swing.filechooser.FileView
    {
        @Override
        public Boolean isTraversable(File f) {
            if (f.getName().startsWith("images")) {
                return false;
            }
            if (f.isDirectory()) {
                return true;
            }
            return false; // added this
        }
    }

    public class SketchFolderFilter extends javax.swing.filechooser.FileFilter {
        public boolean accept(File f) {
            if (f.getName().startsWith("images")) {
                return true;
            }
            if (f.isDirectory()) {
                return true;
            }
            return false;
        }

        public String getDescription() {
            return "Sketch Folders";
        }
    }

    public void saveAs() {
        JFileChooser fc = new JFileChooser()
        {
            public void approveSelection()
            {
                if (getSelectedFile().getName().startsWith("images"))
                    super.approveSelection();
            }
        };

        javax.swing.filechooser.FileFilter filter = new SketchFolderFilter();
        fc.setFileFilter(filter);

        javax.swing.filechooser.FileView view = new SketchFileView();
        fc.setFileView(view);

//      fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        fc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
        fc.setCurrentDirectory(new File("."));
        fc.setSelectedFile( new File("blog") );

        int rv = fc.showSaveDialog(null);

        System.err.println("Option: " + rv);
        if (rv == JFileChooser.APPROVE_OPTION) {
            File newFile = fc.getSelectedFile();
            System.err.println("Save As: " + newFile.getAbsolutePath());
        }
    }

    public static void main(String[] args) {
        fctest main = new fctest();
        main.saveAs();
    }
}

这篇关于JFileChooser“另存为"复合文档 - 覆盖现有的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆