问题
I am writing a program to collect information from two text files to add to tables in a database. In order to permit the user to select his own files I created a non-static method called chooseFile()
that uses JFileChooser
class to present a showOpenDialog
(I've also tried it as a static method with the same results. If this sounds like I'm guessing, you're correct - I'm only so-so with programming).
My understanding is that calls to Swing classes in main()
should be done using invokelater
. This all worked fine (the JVM exits successfully) for one call to chooseFile()
, but when I added a second call to chooseFile()
the JVM keeps running indefinitely. However, the program exits normally with both calls to chooseFile()
if I do so without using invokelater
. Adding System.exit(0)
after the second call in invokelater
also allows the program to exit normally.
From what I have been able to gather, the program won't exit until all the (non-daemon) threads are closed. However, I thought that the purpose for using invokelater
was to push all non-thread safe Swing related activities onto the EDT. Is using System.exit(0)
the best practice here or is there something else I should know about?
Here is my 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);
}
}
});
}
}
回答1:
In your call to showOpenDialog(null)
you pass null
as the parent component for the JFileChooser
. It's been some time since I worked with JFileChooser
, but I seem to remember, that a "magic" JFrame may be constructed, when null
is passed in. It may be possible, that in this use case two "magic" JFrames are created and they prevent termination.
You may want to try to create a JFrame
which serves as parent for both JFileChooser
s so it does not create the automatic frames.
EDIT:
My first take would be this:
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
...
来源:https://stackoverflow.com/questions/33788138/calling-jfilechooser-twice-in-invokelater-causes-program-not-to-exit