The real reason I'm trying to do this is to run a game (infinite) loop when the UI shows, but this shows the same problem.
primaryStage.setScene(new Scene(root));
primaryStage.addEventHandler(WindowEvent.WINDOW_SHOWN, event -> {
System.out.println("Shown");
try {
Thread.sleep(4000);
} catch (Exception e) {
e.printStackTrace();
}
});
primaryStage.show();
This code will result in a console message, then a 4 second wait, then the window actually shows. I can't really find anything on this and it doesn't seem to make much sense since the documentation for WINDOW_SHOWN specifically states it fires just after the window is shown.
Not exactly an answer to the original question but a comment as to what solved a problem whose search brought me here.
I had a need to display an APPLICATION_MODAL custom dialog fired off by a MainScene show event hook.
If I displayed the dialog via showAndWait() the parent stage window decorations never completed rendering correctly until the dialog closed.
If I displayed the dialog via show() the parent rendered correctly yet I still had correct modal event-queue blocking that I needed.
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).
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();
});
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.
Is there a method for a JavaFX controller that gets called when the user leaves that view in the application? The opposite of the initialize() method basically.
I want to do this because I have a page that shows a webcam stream waiting for the user to press a button that takes a snapshot, and I need to close that stream if the user doesn't take a snapshot and leaves the screen. Any other ways of doing this would be appreciated too.
Thanks!
You can use the window's hiding event...
private void detachHook(final Node parent) {
parent.getScene().getWindow()
.addEventFilter(WindowEvent.WINDOW_HIDING, event -> {
//Kill your webcam stream
});
}
You will have to check if you also get the parent as we do in our application, but the window hiding event should work if a node and a scene are present.
I have a horizontal scroll area and dynamically added widgets inside it.
I want it to scroll to the very end whenever a new widget is added, so that the user sees the last widget using this method:
void scrollToEnd()
{
scroll->horizontalScrollBar()->setValue(100000);
}
...
layout->addWidget(widget);
scrollToEnd();
However, there's a delay between calling layout->addWidget() and actual widget appearing. So calling scrollToEnd() does nothing.
If I make apause by, for example, showing a MessageBox, everything works fine.
Is there a way to wait till the widget is displayed, and then scroll the scroll area?
addWidget probably schedules the actual addition of the widget to after the reentering of the event loop, so you should do the same and call the scrollToEnd method asynchronously (it has to be a slot):
layout->addWidget(widget);
QTimer::singleShot(0, this, SLOT(scrollToEnd()));