Alberto acepsut
Alberto acepsut

Reputation: 2022

Run a second stage as dialog

My project has a main GUI (Stage) with some buttons: by right click on a button I would like to run another stage in another package.

Here is the project tree

enter image description here

newprojectx is the package with the main GUI and

togglebuttonDraw.setOnMousePressed(new EventHandler<MouseEvent>() {
      @Override
      public void handle(MouseEvent mouseEvent) {
        if (mouseEvent.isSecondaryButtonDown()){



        }
      }
    });

is the method for right mouse click: I would like to run from this button the .fxml from fibonaccipriceretracement package.

togglebuttonDraw is in NewProjectXController class.

Any help really appreciated.

Edit: this is the .fxml I would like to run by right click

enter image description here

Upvotes: 0

Views: 3679

Answers (2)

Antonio J.
Antonio J.

Reputation: 1760

For small FXML's the solution of Sebastian is good, but if you are experiencing a freeze when you are opening the pop-up, maybe the FXML is too big or you are loading it over the network. In this case the FXMLLoader will block your GUI, so you will need to execute the FXMLLoader in background. You can use a Service that returns the Parent for your Scene, and create the Scene an the stage once the service has been finished.

Here is a full example:

import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Pos;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class Main extends Application {
@Override
public void start(Stage stage) throws Exception {
    VBox vbox = new VBox(10);
    vbox.setAlignment(Pos.CENTER);

    final ProgressIndicator progress = new ProgressIndicator(-1);
    progress.setVisible(false);

    Button button = new Button("Open fxml");
    button.setOnAction(new EventHandler<ActionEvent>() {            
        @Override
        public void handle(ActionEvent event) {
            final Service<Parent> service = new Service<Parent>() {                 
                @Override
                protected Task<Parent> createTask() {   
                    return new Task<Parent>() {                         
                        @Override
                        protected Parent call() throws Exception {
                            //Out of FX Thread
                            String fxml = "/FxmlTest.fxml";
                            Parent root = FXMLLoader.load(getClass().getResource(fxml));
                            return root;
                        }
                    };
                }
            };
            progress.visibleProperty().bind(service.runningProperty());
            service.start();
            service.runningProperty().addListener(new ChangeListener<Boolean>() {
                @Override
                public void changed(ObservableValue<? extends Boolean> value, Boolean oldValue, Boolean newValue) {                 
                    if(!newValue){//The service has ended
                        //In the FX Thread
                        Stage stage = new Stage();
                        Scene scene = new Scene(service.getValue());
                        stage.setScene(scene);
                        stage.show();
                    }
                }
            });
        }
    });

    vbox.getChildren().addAll(button, progress);

    Scene scene = new Scene(vbox);
    stage.setScene(scene);
    stage.show();
}

public static void main(String[] args) {
    launch(args);
}
}

I put a progress indicator to show that the service can take a time while loading.

If you want to check where it is in a FX Thread, you just need to use Platform.isFxApplicationThread().

Hope it helps.

Upvotes: 0

zhujik
zhujik

Reputation: 6574

FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("/fibonaccipriceretracement/FibonacciPriceRetracementDialog.fxml"));
Parent content = (Parent) loader.load();
Stage stage = new Stage();
stage.setScene(new Scene(content));
stage.show();

Upvotes: 2

Related Questions