【问题标题】:altering JFileChooser behaviour : preventing "choose" on enter in file path JTextField改变 JFileChooser 行为:防止“选择”进入文件路径 JTextField
【发布时间】:2011-05-13 01:10:10
【问题描述】:

向 Swing 专业人士问好,这是一个很好的(我希望的)问题。

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

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

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

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

  2. 通过在文件名文本字段中按回车键来防止用户选择具有超过 1GB 数据的目录/文件

这里有几个通用的解决方案选项:

一个。监听 JFileChooser 提供的基于属性的更改(AFAICS 是事后触发的,不会提供我们需要的控制程度)。

b.修补 javax.swing.plaf.basic.BasicFileChooserUI(通过反射,打破私有级别的封装)并更改对

的引用
private Action approveSelectionAction = new ApproveSelectionAction();

以便我们的自定义操作对 1 和 2 进行额外检查。此方法与 plaf 包相关联,如果此操作在此 UI 类下方的某个类中以某种方式被覆盖,则可能会失败。

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

好吧,公共 JFileChooser API 似乎不足以实现该行为,而其他两个选项要么是深度魔法要么是不可移植(长期),甚至两者兼而有之。

那么,问题是:您会选择哪种方法,为什么选择?

【问题讨论】:

    标签: java swing look-and-feel jfilechooser


    【解决方案1】:

    我最近遇到了同样的要求,即在 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”变量提供对此信息的访问。我自己的approveSelection 如下所示:

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

    【讨论】:

    • 效果很好。作为一个鼠标恐惧症,默认功能真的让我很烦,我担心找到解决方案会很困难。
    【解决方案2】:

    关于option2,不需要使用反射来自定义accept Action。您可以只覆盖approveSelection() 方法。比如:

    JFileChooser chooser = new JFileChooser( new File(".") )
    {
        public void approveSelection()
        {
            if (getSelectedFile().exists())
            {
                System.out.println("duplicate");
                return;
            }
            else
                super.approveSelection();
        }
    };
    

    【讨论】:

    • 哦,我的笨蛋,我会测试一下并报告我的发现。
    • 好吧,在某些本应被视为无效的情况下,我完全能够通过不调用 super.approveSelection() 来拦截和解除批准选择事件。这是一个很好的解决方案,再次感谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-16
    • 2019-05-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多