I am trying to close a sub window programatically after certain time. This sub window initOwner is set with main stage. But on closing this sub window, the main window is getting focused. Is there any way to close the sub window(programatically) without gaining focus on main window?
Below is the quick demo of my issue. I tried all the possible ways to close the window. Steps to reproduce:
After starting the application, click the button to open the sub window. This sub window will close automatically after 10seconds.
Meanwhile open any other application (notepad, outlook, browser.. or whatever). While you are working on that application, when the sub window is closed, the main stage gets focus and comes in front of my current application. This is quite annoying to my client.
Note: I cannot remove initOwner(), as I always want to keep my sub window on top of the main window.
Update : Based on the comments, I tried running the demo with different jdk versions (u91, u121 & u211) and in Windows 10. In all three cases , the moment the sub window is closed, the main stage is coming to front. I even tried in a differnt system but the results are same :(
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import javafx.util.Duration;
public class OwnerStage_Demo extends Application {
@Override
public void start(Stage stage) throws Exception {
Button button = new Button("Open Window");
button.setOnAction(e -> {
Stage stg = new Stage();
stg.setScene(new Scene(new StackPane(), 300, 300));
stg.initOwner(stage);
stg.show();
// Window will close automatically after 10secs.
Timeline timeline = new Timeline(new KeyFrame(Duration.millis(10000), x -> {
//stg.close();
//stg.hide();
stg.fireEvent(new WindowEvent(stg, WindowEvent.WINDOW_CLOSE_REQUEST));
}));
timeline.setCycleCount(1);
timeline.play();
});
VBox root = new VBox(button);
root.setSpacing(10);
Scene sc = new Scene(root, 600, 600);
stage.setScene(sc);
stage.show();
}
public static void main(String... a) {
Application.launch(a);
}
}
Update : Attached the gif demonstrating the issue.
Be default, to quit the program is to let the user click the standard window close button, typically represented by an X in the upper-right corner of the window's title bar.
javafx Windows Creating a new Window // create sample content Rectangle rect = new Rectangle(100, 100, 200, 300); Pane root = new Pane(rect); root. setPrefSize(500, 500); Parent content = root; // create scene containing the content Scene scene = new Scene(content); Stage window = new Stage(); window.
Stage Modality The start() method is executed when the JavaFX application is launched (first main() is called which calls launch() which later calls start() ). Notice also, how a new JavaFX Stage object is created, its modality mode set, and then both the primary and the new Stage objects are made visible (shown).
A top level window within which a scene is hosted, and with which the user interacts. A Window might be a Stage , PopupWindow , or other such top level. A Window is used also for browser plug-in based deployments.
- Stack Overflow How to close a JavaFX application on window close? In Swing you can simply use setDefaultCloseOperation () to shut down the entire application when the window is closed. However in JavaFX I can't find an equivalent. I have multiple windows open and I want to close the entire application if a window is closed.
In JavaFX, to create a window, you use Stage class. There are three modelities that you can apply to the Stage through the stage.initModality (Modelity) method. When creating a new Stage, you can set up a parent window for it (also called the window owning it), via the stage.initOwner (parentStage) method.
This sub window will close automatically after 10seconds. Meanwhile open any other application (notepad, outlook, browser.. or whatever). While you are working on that application, when the sub window is closed, the main stage gets focus and comes in front of my current application.
The JavaFX undecorated window gives you a blank canvas, giving freedom to how your window looks without having to accept the default Windows title bar and buttons such as the Minimize, Maximise and Close buttons.
How a window gains the focus depends on a platform (OS + JRE). The platform processes focused window that is why the window may have different behavior on different OS after calling focus request.
There is no way to achieve required behaviour with pure JFX because of the restriction you had set:
Note: I cannot remove initOwner(), as I always want to keep my sub window on top of the main window.
com.sun.javafx.tk.quantum.WindowStage
if (!isPopupStage && owner != null && owner instanceof WindowStage) {
WindowStage ownerStage = (WindowStage)owner;
ownerStage.requestToFront();
}
What you can do is to imitate owner window <- child window
relationship without initializing real owner.
Source:
public class PlainZStage extends Stage {
public PlainZStage(final Window owner) {
init(owner, this::focusedChanged);
}
private void init(final Window owner, final ChangeListener<Boolean> listener) {
showingProperty().addListener(new ChangeListener<Boolean>() {
@Override
public void changed(final ObservableValue<? extends Boolean> observable, final Boolean oldValue,
final Boolean newValue) {
owner.getScene().getRoot().setDisable(newValue);
if (newValue) {
owner.focusedProperty().addListener(listener);
} else {
owner.focusedProperty().removeListener(listener);
showingProperty().removeListener(this);
}
}
});
}
private void focusedChanged(final ObservableValue<? extends Boolean> source, final Boolean oldValue,
final Boolean newValue) {
if (newValue && isShowing()) {
toFront();
}
}
}
Usage:
button.setOnAction(e -> {
final Stage stg = new PlainZStage(stage);
stg.setScene(new Scene(new StackPane(), 300, 300));
stg.show();
// Window will close automatically after 10secs.
final Timeline timeline = new Timeline(new KeyFrame(Duration.millis(10000), x -> {
stg.close();
}));
Alternatively, you could combine JFX&SWING to filter focus events but you will face pure architectural evil :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With