Switching To Primary Scene When Secondary Scene Is Closed - javafx

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).

Related

Javafx Hide Show [duplicate]

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).

javafx: How to get back to original application window without closing the new window?

Apologies for asking such a simple question but english is not my first language, so I cannot find the right word to describe my problem and cannot google up the the right question.
I have a javafx application and there is a button whereby if the user clicks it, it generates a new window (like a display box just to display more info to a user). The problem is when the new window is displayed and I click anywhere of the Javafx application, I cannot get back to it. I have to close the new window first in order to interact with the original javafx application.
How can I have the ability to open the new window on a button click, while retaining the ability to interact the original javafx application without having to close the new window ?
Button moreInfo = new Button("More Info");
moreInfo.setOnAction(e -> {
MoreInfoDisplayBox.display();
});
public class MoreInfoDisplayBox {
public static void display(){
Stage window = new Stage();
window.initModality(Modality.APPLICATION_MODAL);
window.setTitle("More Info");
window.setMinWidth(400);
window.setMinHeight(400);
window.show();
}
}
The behavior you describe is caused by calling
window.initModality(Modality.APPLICATION_MODAL);
(See docs.)
Instead, just use the default, which you can do explicitly with
window.initModality(Modality.NONE);
or of course just omit that line entirely.

setScene() method, JavaFX

I have a program with few fxml files so at different points of program different scene and layout is shown.
some point in a program:
mainStage.setScene(FXMLScene1);
...
later in a program:
mainStage.setScene(FXMLScene2);
...
later in a program:
mainStage.setScene(FXMLScene2);
I wonder what happens to old scene when I use setScene() several times?
There are very complicated methods to change scene(like this https://blogs.oracle.com/acaicedo/entry/managing_multiple_screens_in_javafx1) and my solution is just to make static refference to main stage at MainApplication class so I can manage it everywhere.
public class MainApplication extends Application {
public static Stage parentWindow;
#Override
public void start(Stage stage) throws Exception {
parentWindow = stage;
so it made me wonder if everything is allright with my concept...
You don't have to create a scene to flip screens. You can directly set the root node on the present scene, using setRoot() of the Scene.
This will save you the pain of creating a scene instance every time to want to change the content of your application.
You can use it:
Parent root = FXMLLoader.load(getclass.getResource("some-fxml.fxml"));
scene.setRoot(root);
Just keep in mind the Parent element being used in the FXML that you want to set as the Root Element. From the docs
The application must specify the root Node for the scene graph by setting the root property. If a Group is used as the root, the contents of the scene graph will be clipped by the scene's width and height and changes to the scene's size (if user resizes the stage) will not alter the layout of the scene graph. If a resizable node (layout Region or Control is set as the root, then the root's size will track the scene's size, causing the contents to be relayed out as necessary.
N.B. Please read through the EXAMPLE that you have provided, it uses setScreen( ) instead of setScene( ). The whole example has just one Scene and many Screens, where screens can be considered as any child of the scene graph
Additional data as per comments
If you go through the scene javadoc, you will find that Scene resizes itself to the root size, if no predefined size is present
The scene's size may be initialized by the application during construction. If no size is specified, the scene will automatically compute its initial size based on the preferred size of its content. If only one dimension is specified, the other dimension is computed using the specified dimension, respecting content bias of a root.
Different FXML have different size
In case you have different FXML that you want to set as ROOT nodes and each of them have different sizes.Futhermore, you want to re-size your stage in accordance to every FXML that you load, then you will have to re-initialize the Scene, there is no other way.
Parent root = FXMLLoader.load(getclass.getResource("some-fxml.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
If you set a new scene on your stage and keep no reference to the old scene or objects in it, the old scene will be garbage collected and all resources associated with it will be thrown away (whenever the garbage collector in the Java Virtual Machine decides to do so). If you keep a reference to the old scene (e.g. assign it to a static final variable in your application), then the old scene resources will remain in memory until your application terminates.
If I change the root, how to make Stage change to the new size(size of Layout)?
Use stage.sizeToScene(), which will: "Set the width and height of this Window to match the size of the content of this Window's Scene." The stage sizing process when you invoke this call is similar to when you initially show a stage, but updated for the current scene's content and layout constraints.
The algorithm used is documented in the Scene javadoc: "The scene's size may be initialized by the application during construction. If no size is specified, the scene will automatically compute its initial size based on the preferred size of its content. If only one dimension is specified, the other dimension is computed using the specified dimension, respecting content bias of a root."
what is better, to change the whole scene, or just a root?
I don't think it makes much difference, choose whichever strategy makes the most sense to you.

how to bind scene with stage in javafx2

Actually I want to switch from one scene to another scene on particular event. So i can do that by setting scene of the stage without binding but i want to bind my stage with scene as soon as a flag changes my scene will change automatically....pls help
The JavaFX Demos and Samples Downloads contains an application called FXML-LoginDemo. It demonstrates how to change scenes in a stage. The important part happens in the method replaceSceneContent. As for automatically changing the stage when a flag in your application is updated, there are several ways to do that. I recommend using a PropertyChangeListener or using JavaFX withCDI and then using CDI events. I used the latter approach in my application and it works really well.

QGraphicsScene::changed() always returns a single rect sized to the app window

In a Qt 4.7.1 Windows app, a slot that's connected to QGraphicsScene::changed() is fired as expected but the dirty region count is always 1 and the rect size I get is always the same as my app window. I tried calling QGraphicsView::setViewportUpdateMode(QGraphicsView::MinimalViewportUpdate); but that didn't help.
Is there a way to tell Qt to only give me the area(s) of the page that changed?
An update in a QGRaphicsView is different from the one in a QGraphicsScene. Update in the view is caused by the need to repaint the view. With or without changing the scene. This typical is from window (resize) and view changes (scroll). An change in the scene will also trigger an update to the view.
A change in a scene is the change of the content of the scene. Like adding or removing a item, scaling or translating of the transformation. This will emit the changed() signal. All views displaying that scene will also update themselves for the display.
For example. Scrolling a view around will not generate any scene update since nothing in the scene changed. The paint() function of items in the scene will be called to repaint. But no changed() signal will be emitted from the scene.
If you changed the scale of the scene for instance, the whole scene changed. In addition to the whole repaint, the scene will emit changed() signal and indicates the whole scene changed. But if you add a new item to the scene, changed() should indicate only the rect of the new item.
If you want to know what part of the scene need to be repainted, in addition to calling QGraphicsView::setViewportUpdateMode(), you need to install a event filter to the view and check for QEvent::Paint. Note that the region and rect in QPaintEvent is in local coordinate of the view, which can be different from the scene. But QGraphicsView has many mapping functions to do the conversion.

Resources