Safari убивает Java-апплет, который запустил (бездействующий) JFileChooser - PullRequest
1 голос
/ 09 марта 2012

Мне нужно открыть диалоговое окно открытия файла на веб-странице и попросить пользователя выбрать файл (не для загрузки!).Поскольку мне нужен доступ к полному пути к файлу, я не могу использовать форму / ввод.Таким образом, я использую подписанный Java-апплет.

В моем тестовом случае метод Java-апплета вызывается из функции javascript.Метод апплета открывает диалог открытия файла (JFileChooser).Если оставить на холостом ходу прибл.30 ", апплет убит Safari (*). В моем тестировании Chrome приятнее, он выдает предупреждение" unresponsive ", тогда как Firefox, видимо, не волнует.

IIUC, это Safari-специфичное поведение, но это очень неудобно. Мне нужно, чтобы это диалоговое окно сохранялось до тех пор, пока пользователь не сделает выбор. Я смотрел на многопоточность JFileChooser, но этот путь кажется более сложным, и выполнение всей работы только в Javascriptвозможно, по известным причинам безопасности. У вас есть чистое решение для этого?

(*) JVM заканчивается в InterruptedException

1 Ответ

1 голос
/ 09 марта 2012

Ваша проблема проистекает из того факта, что диалоги в Java ведут себя как блокирующие вызовы методов (на самом деле это удивительный инженерный прием, как они это делают, что я хотел бы, чтобы другие наборы инструментов приняли).Поэтому, когда ваш javascript вызывает метод в коде Java, он ожидает закрытия этого диалога.Браузер обнаруживает, что поток JavaScript не вернулся через некоторое время, и просто решает, что он заблокирован, и убивает его.Следовательно, Java-апплет отключается вместе со страницей.

Вам нужно будет преобразовать это во взаимодействие в асинхронном стиле.Вызов Javascript должен немедленно вернуться.Вы можете использовать SwingUtilities.invokeLater () в Java, чтобы вытолкнуть этот вызов из вызывающего потока Javascript.Хитрость в том, что после закрытия диалогового окна вам нужна Java для вызова Javascript.Таким образом, у вас будет javascript зарегистрировать какой-то механизм обратного вызова.Что-то вроде следующего.Я не могу вспомнить, как работает внешний javascript -> java, так что это просто псевдокод для иллюстрации идеи:

function showFileDialog() {
    applet.showFileDialog( function( filepath ) {
       if( filepath ) {
          alert( "Hey they picked " + filepath );
       } // must have hit cancel if filepath is null
    } );
}

Между тем в Java:

public void showFileDialog( JavascriptFunction someJavascriptFunction ) {
    SwingUtilities.invokeLater( new Runnable() {
        public void run() {
            JFileChooserDialog chooser = new JFileChooser();
            ...
            int option = chooser.showOpenDialog( parent );

            someJavascriptFunction.invoke( option == JFileChooser.APPROVE_OPTION ? 
                                           chooser.getSelectedFile().getAbsolutePath() : 
                                           null );
        }
    });
}
...