代码之家  ›  专栏  ›  技术社区  ›  Anton Kraievyi

更改jFileChooser行为:防止在文件路径jtextfield中输入时“选择”

  •  5
  • Anton Kraievyi  · 技术社区  · 14 年前

    向挥杆职业选手致意,我希望你们能回答一个好问题。

    下面是我看到的任务要求和可能的解决方案。我希望有人有这样一个核心的经验,分享一些关于这方面的想法。

    这不需要编码 或者类似的事情,我只需要 一般建议 关于我需要合作的事实,哪种方法更可靠? 私有的 位于sun.swing和/或javax.swing.plaf包中的符号。

    任务是修改/更改jFileChooser行为(实际上只是一点点)。

    1. 当用户在文件名jtextfield中按Enter,并且该字段包含目录的路径时,不要“选择”该目录,而是切换到该目录。是的,对话框被配置为接受目录,但是我们只需要接受单击“打开”按钮和(可能)双击文件列表表。

    2. 通过在文件名文本字段中按Enter键,防止用户选择数据超过1GB的目录/文件。

    下面是几个通用的解决方案选项:

    a.听取JFileChooser提供的基于属性的更改(AFAICS是在事实发生后触发的,不会提供我们在这里需要的控制程度)。

    b.修补javax.swing.plaf.basic.basicFileChooserUI(通过重定向,破坏私有级封装),并将引用更改为

    private Action approveSelectionAction = new ApproveSelectionAction();
    

    以便我们的自定义操作对1和2执行额外的检查。此方法与plaf包链接,如果此操作在该ui类下面的某个类中被某种方式重写,则可能失败。

    c.遍历jFileChooser组件层次结构,找到jtextfield(显然,在组件树中只出现一次),用我们的自定义检查来装饰挂在jtextfield上的所有操作侦听器。我的调试会话显示,这个jtextfield是jtextfield的一些匿名子类,它位于sun.swing.filepane中。 这种方法似乎更适合面向对象,但对于某些操作系统,可能缺少此文本字段,或者层次结构中也存在其他JTextField。

    好吧,似乎公共jfilechooser API不足以实现这种行为,而其他两个选项要么是深层次的魔力,要么是不可移植的(长期的),要么两者兼而有之。

    所以,问题是:你会选择哪种方法,为什么?

    2 回复  |  直到 9 年前
        1
  •  5
  •   camickr    14 年前

    关于选项2,您不需要使用反射来定制接受操作。您只需重写approveSelection()方法。类似:

    JFileChooser chooser = new JFileChooser( new File(".") )
    {
        public void approveSelection()
        {
            if (getSelectedFile().exists())
            {
                System.out.println("duplicate");
                return;
            }
            else
                super.approveSelection();
        }
    };
    
        2
  •  3
  •   mike rodent    9 年前

    我最近遇到了同样的要求,即在jFileChooser的jtextfield中按Enter键应该使显示的对话框遍历一个目录,而不是从对话框返回。只有单击“打开”按钮才能进行最终选择。

    解决方案相当简单(至少对于我的应用程序而言),它有两个组件(请原谅混乱的格式)。我是这个论坛的新手,我不知道为什么代码显示不正确)。

    1-注册awtlistener以跟踪用户生成的最后一个事件类型

    class MyChooser extends JFileChooser implements java.awt.AWTEventListener {
    
        ...
        MyChooser(){
            Toolkit.getDefaultToolkit().addAWTEventListener(this,
            AWTEvent.MOUSE_EVENT_MASK + AWTEvent.KEY_EVENT_MASK);
            ...
    
        }
    
        int lastEventId;
    
        public void eventDispatched(AWTEvent e) {
            lastEventId=e.getID();
        }
    }
    

    2-重写jFileChooser的approveSelection()方法,并检查批准请求是鼠标事件(可能是由用户单击“打开”按钮引起的)还是由用户按Enter键引起的键事件。“lasteventid”变量提供对此信息的访问。我自己的批准选举如下:

    public void approveSelection() {
        File f=getSelectedFile();
        if (f.exists() && isTraversable(f) && lastEventId ==
            KeyEvent.KEY_PRESSED) {
            setCurrentDirectory(f);
            return;
        }
        super.approveSelection(); }