JFileChooser.showSaveDialog () not showing

I am using the Eclipse IDE and I am trying to call showSaveDialog(null) from another method, which in turn is called from main, but nothing happens when I call it.

Main:

 public static void main(String[] args) { Main main = new Main(); main.pt = main.new PlayThread(); main.generateSound(getSamples(2), 500); main.play(main.sound, 1); if(new Scanner(System.in).nextLine().equals("save")){ System.out.println(main.save()); } } 

All the code before calling main.save() works fine, and main.save() starts as follows:

 public boolean save(){ System.out.println("Calling save"); try{ String saveName = getSaveTo("C:/"); System.out.println("I'm here now"); 

while getSaveTo() looks like this:

 public String getSaveTo(String def){ JFileChooser chooser = new JFileChooser(); System.out.println("Save called"); //chooser.setCurrentDirectory(new File(def)); int resp = chooser.showSaveDialog(null); if(resp == JFileChooser.APPROVE_OPTION){ return chooser.getSelectedFile() + ".wav"; }else return null; } 

After completing the first few functions in main , I type "save" and the console prints:

 Calling save Save called 

But the dialogue never opens, and he never says "I'm here now." Why is that? Also, when I typed

new JFileChooser().showSaveDialog(null)

This is clearly visible, but this will not happen in my save() method. Any ideas why?

EDIT:

Here's a condensed program that has the same problem:

 package com.funguscow; import java.util.Scanner; import javax.swing.JFileChooser; import com.funguscow.Main.PlayThread; public class Test { public static void main(String[] args) { Test main = new Test(); Scanner scan = new Scanner(System.in); boolean should = scan.nextLine().equals("save"); scan.close(); if(should){ System.out.println(main.save()); } } public String getSaveTo(String def){ JFileChooser chooser = new JFileChooser(); System.out.println("Save called"); //chooser.setCurrentDirectory(new File(def)); int resp = chooser.showSaveDialog(null); System.out.println("Save called"); if(resp == JFileChooser.APPROVE_OPTION){ return chooser.getSelectedFile() + ".wav"; }else return null; } public boolean save(){ System.out.println("Calling save"); try{ String saveName = getSaveTo("C:/"); System.out.println("I'm here now"); if(saveName == null)return false; }catch(Exception e){} return false; } } 

You can run it yourself if you want to learn more.


This MCVE may be enough to reproduce the problem, and it seems that a Scanner initialized with System.in interferes with JFileChooser's ability to display an open file dialog, even when it is taken care that the file selection is launched in the Swing event stream:

 import java.util.Scanner; import javax.swing.JFileChooser; import javax.swing.SwingUtilities; public class Test3 { public static void main(String[] args) { Scanner scan = new Scanner(System.in); System.out.print("Enter something and press Enter: "); scan.nextLine(); scan.close(); SwingUtilities.invokeLater(new Runnable() { public void run() { JFileChooser fileChooser = new JFileChooser(); int result = fileChooser.showOpenDialog(null); } }); // JFileChooser fileChooser = new JFileChooser(); // int result = fileChooser.showOpenDialog(null); } } 
+7
java file file-io swing jfilechooser
source share
2 answers

On Windows, Scanner interferes w/ JFileChooser -- why?

tl; dr , strictly speaking, is a user who interferes with JFileChooser , using Scanner JFileChooser for input from the system console ( System.in ). In any case, this concerns the focus of windows and the features of Java Dialog .

Explanation

The error occurs because the dialog appears in the background, because the nextLine() requirement in Scanner on System.in essentially forces the user to switch focus to the console. The application loses focus, so Dialog appears in the background. The code does not “freeze” on its own, it just waits until the user selects a file or makes some other dialog parameter — until he does, he does nothing. If there is some problem with the OS that prevents the background window from being displayed / displayed correctly (for example, a certain window “always in the foreground” prevents this) - well, your application hangs around, waiting for an input event, which is unlikely to happen due to fact no one cannot use the input dialog itself.

For anyone affected - Dialog . I tested this code on Java 8 in Windows XP, Java 8 in Windows 7 and some other configurations - in all cases Dialog was created, possibly hidden in the background of the desktop due to loss of focus. It does not appear in the taskbar, but it appears in the Alt + Tab list. Try to run it outside the IDE, they usually do strange things with the focus of the application when console input is required (due to the "real" console they are redirected to the IDE output window, etc.). Piping data through the pipe < instead of using a "real" console will prevent this behavior.

As far as my imagination is concerned, workarounds will require either focusing on the application framework or creating a permanent frame on the fly to maintain focus where it should be (in the dialog box). Since Dialog of JFileChooser (or any other similar dialogue that can be talked about) is itself a “fire and oblivion” object, it is difficult to get it to the fore without specifying a parent. Therefore, I think that the easiest way to go without a parent Dialog is to simply use the code, for example:

Sample solution

  Scanner scan = new Scanner( System.in ); System.out.print( "Enter something and press Enter: " ); scan.nextLine(); scan.close(); SwingUtilities.invokeLater( new Runnable() { public void run() { JFrame jf = new JFrame( "Dialog" ); // added jf.setAlwaysOnTop( true ); // added JFileChooser fileChooser = new JFileChooser(); int result = fileChooser.showOpenDialog( jf ); // changed //System.out.print( "result: " + result ); jf.dispose(); // added } } ); 

or, if you prefer to interfere with Dialog itself, subclassing it and applying the above setAlwaysOnTop(true) in the createDialog() call (note that createDialog() has protected access in JFileChooser , which makes it impossible to change the behavior without extending the class, like all related Dialog stuff) e.g.

 int result = new JFileChooser() { @Override protected JDialog createDialog( Component parent ) throws HeadlessException { JDialog jDialog = super.createDialog( parent ); jDialog.setAlwaysOnTop( true ); return jDialog; } }.showOpenDialog( null ); 

or even by creating a regular utility class that extends JFileChooser to do just that.

<sub> NB switching to / EDT does nothing here, as it is not related to the thread itself (although multithreading the UI is a source of a problem of sorts). Sub>

+5
source share

I believe that the vaxquis answer will be perfectly correct in that the selector is shown, only outside the current window, since it keeps focus. All this is due to the modality of Dialog and which windows have priority over others on different operating systems (possibly in combination with some IDEs).

I found the following workaround - keeping all your other code exactly the same, extend JFileChooser, and then use MyFileChooser instead of JFileChooser in the getSaveTo() method. I tested my setup (Windows 8, Java 7). Ymmv

 class MyFileChooser extends JFileChooser { protected JDialog createDialog(Component parent) throws HeadlessException { JDialog dialog = super.createDialog(parent); dialog.setAlwaysOnTop(true); return dialog; } } 

This allows you to use the original construct ( .openSaveDialog(null) ) and has the nice added advantage that you can configure other dialog box functions in your overridden createDialog() method if you want.

EDIT

I see that vaxquis has added this method to his answer now, so the answer, I would say, was canonical.

+2
source share

All Articles