6

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

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

这不需要编码或类似的东西,我只需要关于哪种方法更可靠的一般建议,因为我需要使用位于 sun.swing 和/或 javax.swing.plaf 包中的私有符号。

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

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

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

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

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

湾。修补 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 似乎不足以实现这种行为,而其他两个选项要么是深度魔法要么是不可移植的(长期),或者两者兼而有之。

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

4

2 回答 2

6

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

JFileChooser chooser = new JFileChooser( new File(".") )
{
    public void approveSelection()
    {
        if (getSelectedFile().exists())
        {
            System.out.println("duplicate");
            return;
        }
        else
            super.approveSelection();
    }
};
于 2010-11-20T17:29:15.950 回答
3

我最近遇到了同样的要求,即在 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(); } 
于 2014-06-25T04:26:09.393 回答