Prevent/Cancel closing of primary stage in JavaFX

2019-01-25 02:47发布

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?

标签: java javafx-2
4条回答
小情绪 Triste *
2楼-- · 2019-01-25 03:13

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();
                        }

                    }
                });
查看更多
Deceive 欺骗
3楼-- · 2019-01-25 03:21

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

查看更多
Luminary・发光体
4楼-- · 2019-01-25 03:28

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();
    }
});
查看更多
叼着烟拽天下
5楼-- · 2019-01-25 03:29

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);
    }
}
查看更多
登录 后发表回答