0

In my application I used the javafx.stage.FileChooser and for it the JavaFX thread would start. For my frame I set the default close operation to WindowConstants.DISPOSE_ON_CLOSE. When the user would exit the application all GUI would disappear but the application would continue running because of the JavaFX thread still being alive. The interesting thing is that I set Platform.setImplicitExit(true); . The documentation of the function says:"If this attribute is true, the JavaFX runtime will implicitly shutdown when the last window is closed;", but this did not happen. The problem could be solved by setting default close operation to WindowConstants.EXIT_ON_CLOSE or using the javax.swing.JFileChooser instead of FileChooser. I have fixed it, but am interested and would like to understand why the JavaFX thread did not shutdown even though I set the implicit exit and nothing was opened.

Here is a small example program (click button->close file chooser->close application):

public class JFXProblm {
    public static void main(String[] args) {
        EventQueue.invokeLater(() -> {
            new MyFrame();
        });
    }

    private static class MyFrame extends JFrame {

        public MyFrame() {
            setVisible(true);
            setBounds(150, 150, 300, 300);
            setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
            //WindowConstants.EXIT_ON_CLOSE->the application will close, 
            //but that is not the point of the question
            add(new JButton(new AbstractAction("File chooser") {

                @Override
                public void actionPerformed(ActionEvent arg0) {

                    {   
                        // to prepare toolkit
                        new JFXPanel();
                        Platform.setImplicitExit(true);
                    }

                    final FileWrapper f = new FileWrapper();
                    if (Platform.isFxApplicationThread()) {
                        FileChooser fc = new FileChooser();
                        f.setF(fc.showOpenDialog(null));
                    } else {
                        synchronized (f) {
                            Platform.runLater(() -> {
                                synchronized (f) {
                                    FileChooser fc = new FileChooser();
                                    f.setF(fc.showOpenDialog(null));
                                    f.notify();
                                }
                            });
                            try {
                                f.wait();
                            } catch (InterruptedException e) {
                                throw new RuntimeException(e);
                            }
                        }
                    }

                    File file = f.getF();
                    if(file!=null)
                        JOptionPane.showMessageDialog(null, f.getF().toString());

                }
            }));
        }
    }

    /**
     * Used because of the must be final in runnable.
     * If there is a better way please educate me :)
     *
     */
    private static class FileWrapper {
        private File f = null;

        public synchronized File getF() {
            return f;
        }

        public synchronized void setF(File f) {
            this.f = f;
        }
    }
}

I just made this small test and the program does not end, again because of the JavaFX thread.

public class Main {

    public static void main(String[] args) {
        new JFXPanel();
        Platform.setImplicitExit(true);
        Platform.runLater(()->{
            FileChooser fc = new FileChooser();
            fc.showOpenDialog(null);
        });
    }

}
  • Mixing Swing and JavaFX like this is truly inadvisable IMO. Putting synchronized blocks on a UI thread with wait/notify mechanisms is also inadvisable. Just get rid of all the synchronization and rewrite the whole thing in either Swing or JavaFX. – jewelsea Jan 16 '16 at 11:32
  • I did exactly that. I rewritten everything to use swing components. I just made a edit to the question and in the new example the program again never dies. @jewelsea – someone_somewhere Jan 16 '16 at 11:43
  • 1
    That is not the standard structure for a pure JavaFX application, such an application would extend [Application](https://docs.oracle.com/javase/8/javafx/api/javafx/application/Application.html). If you introduce a JFXPanel (which I don't advise for most programs), then you immediately have a hybrid JavaFX/Swing application, and the minimal convoluted structure for such a beast can be found in example 3-1 of the [Oracle JavaFX/Swing integration tutorial](https://docs.oracle.com/javase/8/javafx/interoperability-tutorial/swing-fx-interoperability.htm). – jewelsea Jan 16 '16 at 11:52
  • JFileChooser may create implicit frames. You might like to read my answer for a slightly different problem, but it may solve your issue too: http://stackoverflow.com/a/33790977/1396265 – Rainer Schwarze Jan 16 '16 at 13:25
  • I solved the problem by using JFileChooser and rewriting everything so that it does not use JavaFX. I was just wondering why the JavaFX thread continues to run. It seems that in order to mix it with Swing you have to set EXIT_ON_CLOSE as default close operation. – someone_somewhere Jan 16 '16 at 13:36
  • 1
    Both your sample classes do actually allow the platform to exit for me. JDK 1.8.0_60 on Mac OS X 10.9.5. But this is really not a recommended use case anyway, as indicated in other comments. – James_D Jan 17 '16 at 03:58

0 Answers0