invokelater调用JFileChooser两次导致程序不退出

Calling JFileChooser twice in invokelater causes program not to exit

我正在编写一个程序来从两个文本文件中收集信息以添加到数据库中的表中。为了允许用户 select 他自己的文件,我创建了一个名为 chooseFile() 的非静态方法,它使用 JFileChooser class 来呈现 showOpenDialog (我我也尝试过将它作为静态方法使用,结果相同。如果这听起来像我的猜测,那么你是对的——我对编程只是马马虎虎)。

我的理解是 main() 中对 Swing classes 的调用应该使用 invokelater 完成。对于一次对 chooseFile() 的调用,这一切都工作正常(JVM 成功退出),但是当我添加对 chooseFile() 的第二次调用时,JVM 会无限期地保持 运行。但是,如果我在不使用 invokelater 的情况下调用 chooseFile(),程序会正常退出。在invokelater中第二次调用后加上System.exit(0)也可以让程序正常退出。

据我所知,在关闭所有(非守护进程)线程之前,程序不会退出。但是,我认为使用 invokelater 的目的是将所有非线程安全的 Swing 相关活动推送到 EDT。使用 System.exit(0) 是这里的最佳实践还是我应该了解的其他信息?

这是我的 SSCCE:

package ptMngr;

import java.io.IOException;
import java.nio.file.Path;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFileChooser;
import javax.swing.filechooser.FileNameExtensionFilter;

public class ParticipantManager {

    private Path chooseFile() throws IOException{
        JFileChooser chooser = new JFileChooser();
        FileNameExtensionFilter filter = new FileNameExtensionFilter("Text Files", "txt","csv");
        chooser.setFileFilter(filter);
        int returnVal = chooser.showOpenDialog(null);
        if(returnVal == JFileChooser.APPROVE_OPTION) {
            System.out.println("You chose to open this file: " +
                chooser.getSelectedFile().getName());
        }
        Path path = chooser.getSelectedFile().toPath();
        return path;
    }
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args){
    //        ParticipantManager pm =  new ParticipantManager();
    //        try {
    //            pm.chooseFile();
    //            pm.chooseFile();
    //
    //        } catch (IOException ex) {
    //            Logger.getLogger(ParticipantManager.class.getName()).log(Level.SEVERE, null, ex);
    //        }

        java.awt.EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {

                ParticipantManager pm =  new ParticipantManager();
                try {

                    pm.chooseFile();
                    pm.chooseFile();
                    System.exit(0);
                } catch (IOException ex) {
                    Logger.getLogger(ParticipantManager.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        });
    }
}

在调用 showOpenDialog(null) 时,将 null 作为 JFileChooser 的父组件传递。自从我使用 JFileChooser 以来已经有一段时间了,但我似乎记得,当传入 null 时,可能会构造一个 "magic" JFrame。这可能是可能的用例二 "magic" JFrame 被创建并且它们防止终止。

您可能想尝试创建一个 JFrame 作为两个 JFileChooser 的父级,这样它就不会创建自动框架。

编辑:

我的第一个镜头是这样的:

public static class ParticipantManager {
    JFrame frame;

    private JFrame getFrame() {
        if (frame==null) {
            frame = new JFrame();
            frame.setSize(600, 400);
            frame.setLocationRelativeTo(null);
            // frame.setVisible(true); // <---- worked for me without this call too
        }
        return frame;
    }

    private void close() {
        frame.dispose();
    }

    private Path chooseFile() throws IOException{
        JFrame f = getFrame();
        ...
        int returnVal = chooser.showOpenDialog(f);
    ...

    ...
                pm.chooseFile();
                pm.chooseFile();
                pm.close(); // <----- close the frame
    ...