Locking Modal window called from the FXMLController - java

I'm having a JavaFX-GUI that enables the user to scan.
This process is taking a while. So the user should neither keep clicking around, nor should anyone think the program hung itself.
My solution was a modal window that is just in front of the whole GUI and and disappears itself when everything is finished.
The interface consists of a FXML-Controller, the FXML-File and the MainApp.
So far I'm calling it in the Controller:
Stage stage = Messages.beforeScan(event);
s.scan(filename);
stage.close();
The beforeScan-Method looks like that (Taken from How to create a modal window in JavaFX 2.1 ):
public static Stage beforeScan(Event event) {
Stage stage = new Stage();
try {
Parent root = FXMLLoader.load(
FXMLController.class.getResource("/fxml/Scene.fxml"));
stage.setScene(new Scene(root));
stage.setTitle("My modal window");
stage.initModality(Modality.WINDOW_MODAL);
stage.initOwner(((Node)event.getSource()).getScene().getWindow());
stage.show();
} catch (IOException ex) {
Logger.getLogger(Meldungen.class.getName()).log(Level.SEVERE, null, ex);
}
return stage;
}
Yet this is not successful. If I comment out stage.close(); I can still use my main GUI.
So a different approach:
Instead of importing the Scene from the controller I tired to obtain it from the MainApp-Class:
public static Stage beforeScan(Event event) {
Stage stage = new Stage();
stage.setScene(MainApp.getStage.getScene());
stage.setTitle("My modal window");
stage.initModality(Modality.WINDOW_MODAL);
stage.initOwner(((Node) event.getSource()).getScene().getWindow());
stage.show();
return stage;
}
But this just crashes everything with a StackOverflow.
The Popup (Taken from the example here ) is not helpful either. It is even only opened after the scan.
Using an Alert seemed like a good idea, but doing it that way is not only locking the screen but the program itself:
public Alert beforeScan(Event event) {
javafx.scene.control.Alert alert = new Alert(Alert.AlertType.NONE, "Scan in progress");
alert.showAndWait();
return alert;
}
How should a screen-locking modal window/popup be done properly?

Related

How to block a main window in JavaFX

There is a button in a scene of the main window. When it's clicked, the new window is created, according following code:
public static void create()
{
Stage stage = new Stage();
AnchorPane pane = new AnchorPane();
//Here i add some into pane
stage.setScene(new Scene(pane));
stage.setWidth(500);
stage.setHeight(600);
stage.show();
}
I'd like the main window will remain blocked (i.e. an user won't be able to click on buttons, type text, resize or interact with it with other ways) until the additional window is closed.
Here is a link that shows exactly what you're looking for: http://www.javafxtutorials.com/tutorials/creating-a-pop-up-window-in-javafx/
Here is the main part of the code you need to add:
stage.initModality(Modality.APPLICATION_MODAL);
stage.initOwner(btn1.getScene().getWindow());
stage.showAndWait(); // This forces the program to pay attention ONLY to this popup window until its closed
Hope this helps.

Updating your UI and forcibly waiting before continuing JavaFX

I show here an image of my welcome scene.
The current behavior of the Create New Project button is shown here:
Stage stage = (Stage)((Node)event.getSource()).getScene().getWindow();
stage.hide();
Parent root = FXMLLoader.load(getClass().getResource("/view/scene/configure/NewProjectConfigureScene.fxml"));
Scene scene = new Scene(root);
stage.setTitle("Configure New Project Settings");
stage.setScene(scene);
stage.show();
To explain it in words: the button is pressed -> I get the stage -> hide the current scene -> switch the stage to have a new scene -> re-display the stage. This behavior is working.
I am new to GUI programming so please bear with me as I explain what I need.
I am now trying to add a small feature where when the Create New Project button is pressed, a loading message appears in the current scene, I force the GUI to wait for a few seconds (so that the user has time to see this "loading" message) before continuing onto the next scene. The loading message would look something like this.
I really want to implement this feature because a loading message followed by a wait could be more intuitive and consequently improve my users experience when using the program.
My initial attempt was to do the following:
statusText.setText("Please wait..."); // statusText is the "loading message"
Stage stage = (Stage)((Node)event.getSource()).getScene().getWindow();
try {
Thread.sleep(2000);
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
stage.hide();
Parent root = FXMLLoader.load(getClass().getResource("/view/scene/configure/NewProjectConfigureScene.fxml"));
Scene scene = new Scene(root);
stage.setTitle("Configure New Project Settings");
stage.setScene(scene);
stage.show();
I just read here that you can never sleep the UI thread because it will freeze the entire application. So I've been trying the approach mentioned in the first answer from the above link, which says to use javafx.concurrent.Task, however I have been trying for a long time to no avail.
How do I update the UI, forcibly wait for a few seconds, and then display a new scene?
Instead of sleeping the thread, use a PauseTransition and load your new scene after the pause has finished.
createNewProject.setOnAction(event -> {
statusText.setText("Please wait...");
PauseTransition pause = new PauseTransition(
Duration.seconds(1),
);
pause.setOnFinished(event -> {
Parent root = FXMLLoader.load(
getClass().getResource(
"/view/scene/configure/NewProjectConfigureScene.fxml"
)
);
Scene scene = new Scene(root);
stage.setTitle("Configure New Project Settings");
stage.setScene(scene);
stage.sizeToScene();
});
pause.play();
});
The above code assumes you have just a single stage, so you resize your "Welcome" stage to become the "Configure New Project Settings" stage.
You should try adding in ControlsFX this will help.
You can do the following:
Service<T> service = new Service<T>(){
#Override
protected Task<T> createTask() {
return new Task<T>() {
#Override
protected T call() throws Exception {
//Do your processing here. }
};
}
};
service.setOnSucceeded(event -> {//do your processing});
service.setOnFailed(event -> {//do your processing});
ProgressDialog pd = new ProgressDialog(service);
pd.setContentText("Please wait while the window loads...");
pd.initModality(Modality.WINDOW_MODAL);
pd.initOwner(stage);
service.start();
This will put your code on the background thread. ControlsFX dialogs start and stop with the service.

How could i disable primary stage when a new stage popup

I have button that will popup new stage but primary stage wont disable it still can be click so how to disable the primary stage.
This is my code for stage and scene
private static final Stage stage = new Stage();
private static final Stage newstage = new Stage();
/**
*
*/
#Override
public void start(Stage primaryStage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("MainMenu.fxml"));
Scene scene = new Scene(root);
scene.getStylesheets().addAll(this.getClass().getResource("background.css").toExternalForm());
stage.setScene(scene);
stage.show();
}
public void chgScene (String str) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource(str));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
public void addStage (String str) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource(str));
Scene scene = new Scene(root);
newstage.setScene(scene);
newstage.setResizable(false);
newstage.showAndWait();
}
public void clearStage () {
newstage.close();
}
If any mistaken so sorry since im just new to Java and i need to create a GUI for my project. Thanks for helping.
you need to add this:
newstage.initModality(Modality.APPLICATION_MODAL);
newstage.showAndWait();
see Modality
JavaFx has a various property that you can use, just it depends on the developer how he/she creative on his logic.
mainPane.setDisabled(true);
newPane.showAndWait();
Be advised that initModality() is broken and has been for a long time on the Linux platform runtime.
modal JavaFX stage initOwner prevents owner from resizing, bug?
Yes, that post directly refers to initOwner() but it's the call to initModality() that seems to trigger the bug. You can waste a lot of time playing with kludges that approximate the behavior you need but nothing seems to work just right.

Can't create new stage with multiple AnchorPanes

I'm working on this simple application and trying to create a new stage/window when clicking on a button. I get this work when using a simple fxml-document with only one AnchorPane. In the scene I want to pop-up, there is a TabPane with two tabs. I've imported one fxml-document into each tab, and when I do that a new AnchorPane is created in each tab. So when I click the button in main scene nothing is happening. I really don't know how to solve this, does anybody have any ideas?
This is the code I'm using right now to show a new stage.
#FXML
private void showAddStage(ActionEvent event) {
try {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("Add.fxml"));
Parent root = (Parent) fxmlLoader.load();
Stage stage = new Stage();
stage.setScene(new Scene(root));
stage.show();
} catch (IOException e) {}
}

Executable Jar limited to one window with JavaFX

I am building a JavaFX application through E(fx)clipse and Java Scene Builder.
The basic functionality is a login window. Once logged in, new window opens and the login window disapears. Right now it's just at the prototype stage.
When running out of ecplise, the functionality I want is all there. Login window shows up on start (code looking as such)
#Override
public void start(Stage primaryStage) {
try {
Parent root = FXMLLoader.load(getClass().getResource("view/login.fxml"), ResourceBundle.getBundle("ca.sportstats.resources.labels"));
primaryStage.setTitle("SportStats Live Update Tool : Login");
primaryStage.setScene(new Scene(root, 450, 300));
primaryStage.show();
} catch (IOException e) {
//Change this to open a small popup window.
System.out.println("Could not deploy");
}
}
public static void main(String[] args) {
launch(args);
}
There is one button on this window that simply opens another (the login logic will come later and not an issue here).
btnLogin.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
//TODO: Login logic.
//On success allow to open the tool (aka main window);
Parent root;
try {
root = FXMLLoader.load(getClass().getResource("../view/selector.fxml"), resources);
Stage stage = new Stage();
stage.setTitle("Selector");
stage.setScene(new Scene(root, 450, 450));
stage.show();
//hide this current window
((Node)(event.getSource())).getScene().getWindow().hide();
} catch (IOException e) {
e.printStackTrace();
}
}
});
This works no problem in Ecplise. BUT! When I build this (in the fashion described on the e(fx)clipse tutorials I get an executable jar, but only get the login window. When I click my button the 2nd window doesn't show up.
The problem I think is that in jars you can't do relative paths. Inside Eclipse you are running on the filesystem where this is not a problem

Categories