I would like to open a window with a progress bar when I quit my application while some operations run.
I tried to put my code in the stop method from the Application class but javafx is already down at this moment.
I did the same thing in the first windows like this:
primaryStage.setOnCloseRequest(event -> {
Stage loading = new Stage();
loading.initModality(Modality.WINDOW_MODAL);
loading.initOwner(primaryStage);
loading.setScene(new Scene(new Group(JfxUtils.loadFxml(new FXMLLoader(), FxmlFileConstantes.LOADING))));
loading.show();
});
But same thing, it doesn't work.
How can I do this ?
Thanks.
Consume the close request event in your onCloseRequest event handler.
event.consume();
This will stop the window from closing, which, if the window is the last window in the application, would trigger an application shutdown.
Alternately, you can set Platform.setImplicitExit(false), in which case "the application will continue to run normally even after the last window is closed, until the application calls exit()".
The JavaFX application lifecycle is defined in the javadoc of the Application class, which you should probably read to get some more background information.
Related
I am using JavaFX 11 and a newbie.
I have a single stage with two scenes: a primary scene that shows on start and a secondary scene that is switched to and shown when I press a certain button on the main scene. On the secondary scene, I want to be able to switch back to the main scene when I click the close X button on the top right of the window instead of having the entire application close.
I currently have a method for the cancel button that looks like this:
public void cancelButtonPushed(ActionEvent event) throws IOException {
Parent parent = FXMLLoader.load(getClass().getResource("ExampleMainScreen.fxml"));
Scene scene = new Scene(parent);
Stage window = (Stage) ((Node) event.getSource()).getScene().getWindow();
window.setScene(scene);
window.show();
}
This method allows me to switch back to the main scene when the Cancel button is pushed. However, I am lost trying to find something that can be used any time the user clicks the close X on the secondary scene.
First, get the terminology right, my guess is that you have two Stages. Scenes can be displayed inside those.
Second, Scene Builder (and the FXML it produces) does not manage stages, it only constructs nodes (and event handling for those nodes) that are placed inside scenes. So, you won't find the hooks you need to integrate with the window close functions in SceneBuilder or FXML.
Third, when a user wants to close a window (a stage is a kind of window), then an event will be emitted, which you can action onCloseRequest.
Fourth, somehow you have already managed to create a second stage, probably by calling new Stage(). This will provide you with a reference to the stage which you can set your close request on:
Stage secondaryStage = new Stage();
Stage setScene(secondaryScene);
secondaryStage.setOnCloseRequest(e -> primaryStage.show());
This will show your primary stage (which I guess you hid earlier), when the secondary stage is being closed, but before it has actually closed.
Next, read up on the Application lifecycle, specifically see the section which references Platform.setImplicitExit(boolean implicitExit):
If this attribute is true, the JavaFX runtime will implicitly shutdown when the last window is closed; the JavaFX launcher will call the Application.stop() method and terminate the JavaFX application thread. If this attribute is false, the application will continue to run normally even after the last window is closed, until the application calls exit(). The default value is true.
Note, that, you probably don't need to explicitly set the implicit exit flag if you handle the stage switching as outlined previously, but I provide the info for you in case you need to understand it.
Finally, consider whether you really should be creating new stages for your application and this particular task or just replacing the content in a single stage (similar to how a web browser works).
I have an application with a JavaFX Stage and a SWT Shell. There are controles in the JavaFX stage that alter properties of the SWT widgets in the Shell and some JaveFX controles that are informed about changes in the SWT widgets.
Of course, everything with JavaFX has to happen in the JavaFx application thread and everything with SWT widgets has to happen in the SWT Thread.
I first tried to have one thread for each and switch thread when ever i switch the context. this was very annoying and i decided to no longer follow this approach.
Instead Create the SWT window inside the JavaFX Application thread so that the two UIs run on the same thread. Everything works fine this way except one thing
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
SWT need this snippet, otherwise non of the widgets react on events and SWT needs this to be on the same thread like everything else too. But this snippet is blocking, so as soon as i use it JavaFX freezes.
I know having SWT and JavaFX windows is probably a very odd use case but is there a solution to this?
Just to clarify:
i don't want JavaFX Nodes inside SWT Widgets
I don't want SWT Widgets inside JavaFX Nodes.
SWT and JavaFX can operate in the same thread. A little trick to achieve that is to create a dummy FXCanvas instance before calling any other JavaFX code. FXCanvas is normally used to embed FX controls into SWT; even if you don't need that, the FXCanvas constructor initializes JavaFX properly to work in SWT interoperability mode.
The below code snippet demonstrated an SWT shell and a JavaFX stage working together. Both SWT and JavaFX button click handlers execute on JavaFX Application thread.
public static void main(String[] args) {
Display display = Display.getDefault();
new FXCanvas(new Shell(), SWT.NONE);
Stage primaryStage = new Stage();
Button fxbutton = new Button("JavaFX button");
Scene scene = new Scene(fxbutton);
fxbutton.addEventHandler(MouseEvent.MOUSE_CLICKED, mouseEvent -> System.out.println("FX event, thread=" + Thread.currentThread().getName()));
primaryStage.setScene(scene);
primaryStage.show();
Shell shell = new Shell(display, SWT.CLOSE);
shell.setLayout(new FillLayout());
org.eclipse.swt.widgets.Button swtbutton = new org.eclipse.swt.widgets.Button(shell, SWT.PUSH);
swtbutton.setText("SWT button");
swtbutton.addListener(SWT.Selection, event -> System.out.println("SWT event, thread=" + Thread.currentThread().getName()));
shell.open();
shell.pack();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
}
When I press the red close button, I want the window not to close on JavaFX.
Any suggestions?
From the Javadocs for Window.setOnCloseRequest():
Called when there is an external request to close this Window. The installed event handler can prevent window closing by consuming the received event.
So all you need is
stage.setOnCloseRequest(Event::consume);
or, if you are going to perform other actions as well:
stage.setOnCloseRequest(event -> {
// do some stuff...
event.consume();
});
I need to creat an app that shows the primary stage to the user, and if the user closes the stage, instead of finishing the application, it should just hide the stage for later use.
On swing we could just call setVisible(false) to a JFrame or JDialog, but how to do it on JavaFX?
Once the JavaFX toolkit has started, by default it will close down when the last visible window is closed.
To prevent this, you can call
Platform.setImplicitExit(false);
You typically do this in your start(...) method, though it can be called from any thread.
To exit the application, you would then need to call
Platform.exit();
(as the application no longer exits automatically).
In my Flex (Flash Builder 4) Air application, I have a spark window , and have set the close="" event handler (also tried the 'closing' event) to a method that pops up an alert confirming if they want to close the window.
This worked fine in my normal browser based app as a TitleWindow, but now that it's an Air app with a native spark window, it's not working. I never see the alert dialog, and if I debug trace, it does in fact go in to my close handler method, but visually I can see the window is already gone from the screen.
In an AIR application, how do you add a confirmation dialog for when they click the "x" to close the window?
From the docs it looks like closing would be the one to do it, copied from the docs below:
closing Event
Event Object Type: flash.events.Event
property Event.type = flash.events.Event.CLOSING
Runtime Versions: AIR 1.0
Dispatched by this NativeWindow object immediately before the window is to be closed. This event can be canceled to prevent the window from being closed.
The Event.CLOSING constant defines the value of the type property of a closing event object.
This event has the following properties:
Property Value
bubbles false
cancelable true; canceling this event object stops the close operation.
currentTarget The object that is actively processing the Event object with an event listener.
target The object whose connection is to be closed.
Taken from:
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/NativeWindow.html#event:closing
It says close does happen after the window is closed but closing should be right before and can be cancelled to stop the window from closing.