26

As the title says, my question is, how can I prevent/cancel closing of primary stage in JavaFX 2.2? I have done some research on Google, and the following two links seemed to address the issue:

I tried the methods explained by those two links, but sadly for me, none of them works. So, without further ado, here is what I had done.

Firstly, I tried to attach an OnCloseRequest to the primaryStage as follows.

primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>() {
    @Override
    public void handle(WindowEvent event) {
        if (!canExit()) {
            event.consume();
            primaryStage.show(); // I tried without this line also.
        }
    }
});

When canExit() returns false, I tried to prevent the event from propagating further and cause to exit the app by callingevent.consume(). But the stage is getting closed/hidden and I got the following error messages on Netbeans output window. It keeps coming repeatedly until I force close the app from Netbeans.

(java:6731): Gtk-CRITICAL **: IA__gtk_widget_get_visible: assertion `GTK_IS_WIDGET (widget)' failed

(java:6731): Gtk-CRITICAL **: IA__gtk_widget_get_visible: assertion `GTK_IS_WIDGET (widget)' failed

(java:6731): Gtk-CRITICAL **: IA__gtk_widget_get_visible: assertion `GTK_IS_WIDGET (widget)' failed

Having tasted failure in this attempt, I changed OnCloseRequest to OnHiding with the expectation of success.

primaryStage.setOnHiding(new EventHandler<WindowEvent>() {
    @Override
    public void handle(WindowEvent event) {
        if (!canExit()) {
            event.consume();
            primaryStage.show(); // I tried without this line also.
        }
    }
});

Although, I tasted failure in this attempt too, I think I have made some progress. There is no error messages this time, and no need to force close the application from Netbeans.

Then I read about some magic method named setImplicitExit() in the Platform class. Thinking that this is what I was missing, I tried Platform.setImplicitExit(false); with both of the two methods as follows:

  1. OnCloseRequest version

    Platform.setImplicitExit(false);
    
    primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>() {
        if (!canExit()) {
            // ...
        } else {
            Platform.exit();
        }
    });
    

    No difference, the stage gets closed/hidden, and the same error message comes repeatedly.

  2. OnHiding version

    Platform.setImplicitExit(false);
    
    primaryStage.setOnHiding(new EventHandler<WindowEvent>() {
        if (!canExit()) {
            // ...
        } else {
            Platform.exit();
        }
    });
    

    Beginning on a positive note, the application doesn't get exited as earlier. But, the negative note is that the stage is still getting closed/hidden.

Now, I am out of weapons/equipments in my armoury to solve it, and so I am here to request the help of you heroes and champions. So, How can I solve this problem or what have I done wrong or what am I missing?

Community
  • 1
  • 1
Jomoos
  • 12,823
  • 10
  • 55
  • 92

4 Answers4

32

I have used following code in my application and it works perfectly,

Platform.setImplicitExit(false);

primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>() {
    @Override
    public void handle(WindowEvent event) {
        event.consume();
    }
});
Adam Jensen
  • 541
  • 1
  • 10
  • 25
Shreyas Dave
  • 3,815
  • 3
  • 28
  • 57
  • 2
    I tried the same and the window gets hidden/closed and the error(`(java:3187): Gtk-CRITICAL **: IA__gtk_widget_get_visible: assertion 'GTK_IS_WIDGET (widget)' failed`) appears continuously on console/terminal until I force quit the app. – Jomoos Jun 14 '13 at 05:42
  • Which OS you are using ? If it is MAC or ubuntu such errors are common, you can simply ignore it if not affecting your application. – Shreyas Dave Jun 14 '13 at 06:31
  • I am using Fedora 18, and the problem is that I cannot prevent the stage from closing/hidden if there are some unsaved changes in the app, if I ignore this section. – Jomoos Jun 14 '13 at 11:25
  • @Jomoos did you find a solution? same problem here! – Joao Guilherme Sep 06 '13 at 19:59
  • @Wamasa No, I haven't. Currently, the application works without the functionality. As per one of the above comment that it works on windows, it may be a problem with Linux and GTK. – Jomoos Sep 07 '13 at 12:55
  • This works for me in the latest Java 8 builds - where you can do this instead: - primaryStage.setOnCloseRequest(WindowEvent::consume); – Andrew B Sep 15 '13 at 23:18
  • Great tip. Works for me, but be aware that by setting ImplicitExit to false, you'll need to manually call Platform.exit() in some situations. For me, it was switching back and forth between controllers/views, then clicking my own Exit button, rather than the exit button at the top. You'll know if this is happening because your IDE will keep running after you close, or it'll be running multiple instances that you've exited already. – crapolantern May 08 '20 at 15:07
3

I think you got the onCloseRequest() concept wrong. If you consume the event you cancel the closing! So it works the other way round, if canExit() returns false you consume the event

Pramod
  • 768
  • 1
  • 12
  • 27
tomsontom
  • 5,856
  • 2
  • 23
  • 21
  • Thanks for noting that, I edited my question. The condition is different in the code on my project, I used `canExit()` to make the code snippet more readable. But, it still doesn't answer for the error I am getting. – Jomoos Jun 09 '13 at 07:36
  • 1
    I still don't understand why you call primaryStage.show! The Stage is not closed at all so why call show? – tomsontom Jun 09 '13 at 21:03
  • Initially, I tried without that line and the stage is getting closed/hidden. Then I thought may be the stage is closed when the event is fired, and so putting a `show` will do the trick. That too doesn't work. I have already commented about that line in question as `I tried without this line also.` – Jomoos Jun 09 '13 at 21:18
3

I think this is a bug with JavaFX for Linux. I ran in to the same problem on Javafx 2.2.21-b11. Depending on the context the GTK errors may or may not be present, but either way consuming the close request event didn't prevent the window from closing (yet the process continues to run). The same app on Windows behaved as I would expect. So at best we have a difference in behavior across platforms.

I filed a bug report you can upvote if you'd like: https://javafx-jira.kenai.com/browse/RT-33295

Here's the source of my test app

import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;

public class Boom extends Application {
    @Override
    public void start(final Stage primary)  {
        System.out.println(com.sun.javafx.runtime.VersionInfo.getRuntimeVersion());
        primary.setOnCloseRequest(new EventHandler<WindowEvent>() {
            @Override
            public void handle(WindowEvent e) {
                e.consume();
            }
        });
        primary.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}
kylejmcintyre
  • 1,898
  • 2
  • 17
  • 19
  • And they responded by marking it a duplicate and with the following response: "This issue is already fixed in JDK 8 and 7u40." – kylejmcintyre Oct 07 '13 at 15:12
0

That worked for me

                stage.setOnCloseRequest(new EventHandler<WindowEvent>() {  
                    @Override
                    public void handle(WindowEvent event) {
                        AlertHelper addMore = new AlertHelper("Exit application? Any unsaved data will be lost", "Attention", "Confirmation Required");
                        boolean actionNeeded = addMore.populatePopup();
                        if (actionNeeded) {
                            System.exit(0);
                        } else {
                            event.consume();
                        }

                    }
                });