изменение поведения JFileChooser: предотвращение «выбора» при вводе в пути к файлу JTextField - PullRequest
5 голосов
/ 20 ноября 2010

Привет Swing Pros, вот хороший (надеюсь) вопрос для вас.

Ниже приведены требования к задачам и возможные решения, которые я вижу.Я хотел бы, чтобы кто-то, у кого был такой тяжелый опыт, поделился некоторыми мыслями об этом.

Это не требует кодирования или чего-то подобного, мне просто нужен общий совет относительно того, какой подход является более надежным в отношении того факта, что мне нужно работать с private символы, которые находятся в пакетах sun.swing и / или javax.swing.plaf.

Задача состоит в том, чтобы изменить / изменить поведение JFileChooser (на самом деле, немного).

  1. когда пользователь нажимает, введите в имени файла JTextField, и поле содержит путь к каталогу, не «выбирайте» каталог, а переключайтесь на него.Да, диалог настроен на прием каталогов, но нам нужно принимать только щелчки по кнопке «Открыть» и (возможно) двойные щелчки в таблице списка файлов.

  2. предотвращатьпользователь выбирает каталог / файл с данными более 1 ГБ, нажимая клавишу ввода, введите в текстовое поле имени файла

Вот несколько основных вариантов решения:

a.прислушайтесь к изменениям на основе свойств, которые предоставляет JFileChooser (которые AFAICS запускаются после факта и не обеспечат необходимую нам степень контроля).

b.повозиться с javax.swing.plaf.basic.BasicFileChooserUI (через рефракцию, нарушив инкапсуляцию частного уровня) и изменить ссылку на

private Action approveSelectionAction = new ApproveSelectionAction();

, чтобы наше пользовательское действие выполняло дополнительные проверки для 1 и 2. Этот подход связывается с пакетом plaf и может завершиться ошибкой, если это действие каким-то образом переопределено в некотором классе ниже этого класса пользовательского интерфейса.

c.Пройдите по иерархии компонентов JFileChooser, найдите JTextField (который, по-видимому, должен встречаться в дереве компонентов только один раз), украсьте всех слушателей действий, висящих на этом JTextField, нашими пользовательскими проверками.Мой сеанс отладки показывает, что этот JTextField является некоторым анонимным подклассом JTextField, живущим в sun.swing.FilePane.Этот подход кажется более подходящим для OO, но есть вероятность, что для некоторых ОС это текстовое поле отсутствует или в иерархии также присутствует какое-то другое JTextField.

Что ж, похоже, что публичный API JFileChooserнедостаточно для достижения такого поведения, в то время как два других варианта - либо глубокая магия, либо непереносимая (долгосрочная), либо даже обе.

Итак, вопрос в том, какой подход вы бы выбрали и почему?

Ответы [ 2 ]

5 голосов
/ 20 ноября 2010

Что касается option2, вам не нужно использовать рефлексию для настройки действия принятия Вы можете просто переопределить метод ApproveSelection (). Что-то вроде:

JFileChooser chooser = new JFileChooser( new File(".") )
{
    public void approveSelection()
    {
        if (getSelectedFile().exists())
        {
            System.out.println("duplicate");
            return;
        }
        else
            super.approveSelection();
    }
};
3 голосов
/ 25 июня 2014

Недавно я столкнулся с тем же требованием, то есть нажатие клавиши Enter в JTextField JFileChooser должно привести к тому, что отображаемое диалоговое окно пересекает каталог, а не возвращается из диалогового окна.Только нажатие на кнопку «Открыть» должно привести к окончательному выбору.

Решение было довольно простым (по крайней мере для моего приложения) и состояло из двух компонентов (простите за испорченное форматирование. Я новичок в этом форуме и не уверен, почему код не отображаетсяправильно).

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 - Переопределить метод ApproveSelection () в JFileChooser и проверить, является ли утверждениезапрос - это результат события мыши (вероятно, вызванного нажатием кнопки «Открыть») или ключевого события, вызванного нажатием клавиши «Ввод».Переменная lastEventId обеспечивает доступ к этой информации.Мой собственный выбор утверждения выглядит следующим образом:

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