Issue
Here is a simple JavaFX Program. It comppiles and runs normally util the button is clicked upon.
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
public class Window extends Application
{
@Override
public void start(Stage primary)
{
primary.setTitle("Window");
Button b = new Button("Clickez-vous moi!");
VBox vb = new VBox();
vb.getChildren().add(b);
primary.setScene(new Scene(vb, 400,400));
b.setOnAction( e -> Platform.exit());
primary.show();
}
}
}
This is the error message I get.
Java has been detached already, but someone is still trying to use it at -[GlassViewDelegate dealloc]:/Users/jenkins/workspace/OpenJFX-mac/modules/javafx.graphics/src/main/native-glass/mac/GlassViewDelegate.m:198
0 libglass.dylib 0x000000012a1dbf92 -[GlassViewDelegate dealloc] + 290
1 libglass.dylib 0x000000012a1e1c9c -[GlassView3D dealloc] + 252
2 libobjc.A.dylib 0x00007fff645894ea _ZN19AutoreleasePoolPage12releaseUntilEPP11objc_object + 134
3 libobjc.A.dylib 0x00007fff6456f440 objc_autoreleasePoolPop + 175
4 CoreFoundation 0x00007fff2e45f66e __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
5 CoreFoundation 0x00007fff2e45f594 __CFRunLoopDoObservers + 457
6 CoreFoundation 0x00007fff2e40272b __CFRunLoopRun + 1219
7 CoreFoundation 0x00007fff2e401fe3 CFRunLoopRunSpecific + 499
8 libjli.dylib 0x000000010735b619 CreateExecutionEnvironment + 399
9 libjli.dylib 0x000000010735775e JLI_Launch + 1354
10 java 0x000000010734dca5 main + 375
11 libdyld.dylib 0x00007fff658dc2e5 start + 1
MAC:Wed Dec 04:13:10:426>
I am running the latest version of MACOSX Catalina.
Solution
USE
stage.setOnCloseRequest((event) -> {
Platform.exit();
});
and invoke .close() in the button.onAction() method like so:
button.setOnAction((event) -> {
stage.close();
});
the old style annonymous inner class impl for both event types is as follows:
button.setOnAction(new EventHandler<ActionEvent>() { // note event handler class (ACTION)
@Override
public void handle(ActionEvent event) {
stage.close();
}
});
and
stage.setOnCloseRequest(new EventHandler<WindowEvent>() { // note event handler class (WINDOW)
@Override
public void handle(WindowEvent event) {
Platform.exit();
}
});
Curiously enough, I can run your code on windows and it gives off the BUILD SUCCESSFUL message after clicking the button. so I might be talking complete bollocks.
Nevertheless, there is a difference between event handling at OS level so it should be worth taking the time to CTRL C; CTRL V some code.
edit...
Also I've noticed you're lacking a main method in the application class which is kind of weird for me to see.
I'm pretty sure I tried spawning 2 distinct Application instances at some point in the past and was unable to do so for various javaFX reasons, so if you managed to pull it off, it's possible you're calling the platform.close() routine from the wrong primaryStage
look for something like
public static void main(String[] args) {
Application.launch(args); // this directly references the class it's housed in since it expects to be in xxxx extends Application{} classes
}
or
public static void main(String[] args) {
LauncherImpl.launchApplication(someClass.class, args); // this can be used to launch any class as long as it extends Application.class.
}
Lastly, make sure you're not doing something stupid like having
Window x = new Window(); // pretty sure you can't actually do this but fk knows.... can't be bothered to check.
x.start();
Called from somewhere in your code.
Application =/= Application Windows.
If you want to create a multi-window application, all you need to do is something like:
public class ProperMultiWindowApp extends Application {
public static void main(String[] args) {
Application.launch(args);
}
@Override
public void start(Stage primary) {
primary.setTitle("Window");
Button b = new Button("Clickez-vous moi!");
VBox vb = new VBox();
vb.getChildren().add(b);
primary.setScene(new Scene(vb, 400, 400));
b.setOnAction(e -> primary.close());
Stage secondary = new Stage();
secondary.setScene(new Scene(new HBox(new Label("here be content zeh 2nd"))));
Stage tertiary = new Stage();
tertiary.setScene(new Scene(new HBox(new Label("here be content le 3rd"))));
primary.show();
secondary.show();
tertiary.show();
primary.setOnCloseRequest(e -> Platform.exit());
}
@Override
public void stop() throws Exception {
System.out.println("proof that this is stopping"); // this should be called during Platform.exit();
super.stop();
}
}
Note that for standard JavaSE using JavaFX, the class that you start the application in is what the javaFX JVM considers to be the main class.
If all this fails it's either a bug, or something to do with your mac.... since it's a mac.
If this is the case, I wholeheartedly advise you to proceed to repeatedly bash that thing against a rock in order to ensure that the application is effectively closed.
Answered By - EverNight