Safari杀死了启动(空闲)JFileChooser的Java applet

时间:2012-03-09 13:41:04

标签: java safari applet jfilechooser

我需要在网页中弹出一个文件打开对话框,让用户选择一个文件(不用于上传!)。因为我需要访问完整的文件路径,所以我不能使用表单/输入。因此,我使用签名的Java小程序。

在我的测试用例中,从javascript函数调用Java applet方法。 applet方法打开一个文件打开对话框(JFileChooser)。如果闲置大约。 30英寸,小程序被Safari(*)杀死。在我的测试中,Chrome更好,它会弹出“无响应”警报,而Firefox显然不关心。

IIUC,这是一种特定于Safari的行为,但它非常不方便。我需要该对话框才能保持用户直到用户做出选择。我看了线程JFileChooser但是这条路似乎更复杂,并且由于已知的安全原因,单独使用Javascript完成所有工作是不可能的。你有一个干净的解决方案吗?

(*)JVM以InterruptedException结束

1 个答案:

答案 0 :(得分:1)

你的问题源于这样一个事实:Java中的对话框表现为阻塞方法调用(它实际上是一个令人惊奇的工程技巧,他们希望其他工具包可以采用它)。因此,当您的javascript将方法调用到Java代码上时,它正在等待该对话框被解除。浏览器检测到javascript线程暂时没有返回,只是确定它已经死锁并将其杀死。因此,Java applet随页面一起关闭。

您需要将其转换为异步样式交互。 Javascript调用应该立即返回。您可以使用Java中的SwingUtilities.invokeLater()将该调用从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 );
        }
    });
}