4

EDIT: I have an alert box that pops up if the user clicks "Delete" for removing an item in a ListView. It works, but I would like it to pop over the original stage. It showed up in my first monitor. Is there any way to set the position of the alert when it's shown?

Note, the "owner" is in a different class, and I created everything with Scenebuilder/FXML. I cannot figure out how to get initOwner() to work. Here is the "Main" class:

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Assignment_5 extends Application {
    public Stage primaryStage;

    @Override
    public void start(Stage primaryStage) throws Exception{
        Parent root = FXMLLoader.load(getClass().getResource("Assignment_5.fxml"));
    primaryStage.setTitle("Plant Pack");
    primaryStage.setScene(new Scene(root, 1200, 500));
    primaryStage.show();
}

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

Here is the working code within the Controller class. It's not necessary to implement the modality of this alert, but it would be a nice addition to make it more convenient. I simply don't know how to pass the main Window from the Main class to this:

    protected void handleDeleteButtonClick(ActionEvent event) {
    Alert alertBox = new Alert(Alert.AlertType.CONFIRMATION, "Confirm Delete", ButtonType.OK, ButtonType.CANCEL);
    alertBox.setContentText("Are you sure you want to delete this " + plantType.getValue().toString().toLowerCase() + "?");
    alertBox.showAndWait();
    if(alertBox.getResult() == ButtonType.OK) {
        int selectedPlant = plantList.getSelectionModel().getSelectedIndex();
        observablePlantList.remove(selectedPlant);
    }
    else {
        alertBox.close();
    }
}

I understand this is fairly new, so it's difficult to find many resources. If anyone knows any info I may have missed, please let me know. Thanks for any help offered. I am using Java 8 with IntelliJ 14.1.5.

DevOpsSauce
  • 1,319
  • 1
  • 20
  • 52
  • What relevance does a jQueryUI dialog have to a JavaFX dialog? – jewelsea Nov 21 '15 at 01:29
  • 2
    I haven't tried this, but you might like to try initializing the [modality](https://docs.oracle.com/javase/8/javafx/api/javafx/scene/control/Dialog.html#initModality-javafx.stage.Modality-) and [owner](https://docs.oracle.com/javase/8/javafx/api/javafx/scene/control/Dialog.html#initOwner-javafx.stage.Window-) before showing your alert. – jewelsea Nov 21 '15 at 01:30
  • @jewelsea I have no idea. That was the link provided in a JavaFX question. Haha. I was just stating that since this site can be picky about duplicate questions. – DevOpsSauce Nov 21 '15 at 01:56

1 Answers1

8

As @jewelsea suggests, setting the modality and owner for the alert box will assure that the alert will appear over the stage, even if the stage is moved.

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.ListView;
import javafx.scene.layout.BorderPane;
import javafx.stage.Modality;
import javafx.stage.Stage;

public class DeleteAlertDemo extends Application {

    Stage owner;
    ObservableList<String> observablePlantList;
    ListView<String> plantList;

    protected void handleDeleteButtonClick(ActionEvent event) {
        String item = plantList.getSelectionModel().getSelectedItem();
        Alert alertBox = new Alert(Alert.AlertType.CONFIRMATION, "Confirm Delete", 
                ButtonType.OK, ButtonType.CANCEL);
        alertBox.setContentText("Are you sure you want to delete this " 
                + item.toLowerCase() + "?");
        alertBox.initModality(Modality.APPLICATION_MODAL); /* *** */
        alertBox.initOwner(owner);                         /* *** */
        alertBox.showAndWait();
        if (alertBox.getResult() == ButtonType.OK) {
            int selectedPlant = plantList.getSelectionModel().getSelectedIndex();
            observablePlantList.remove(selectedPlant);
        } else {
            alertBox.close();
        }
    }

    @Override
    public void start(Stage primaryStage) {
        owner = primaryStage;                /* *** */
        Button deleteBtn = new Button();
        deleteBtn.setText("Delete");
        deleteBtn.setOnAction(this::handleDeleteButtonClick);

        observablePlantList = FXCollections.observableArrayList("Begonia", 
                "Peony", "Rose", "Lilly", "Chrysanthemum", "Hosta");
        plantList = new ListView<>(observablePlantList);
        plantList.getSelectionModel().select(0);
        BorderPane root = new BorderPane();
        root.setCenter(plantList);
        root.setRight(deleteBtn);

        Scene scene = new Scene(root, 300, 250);

        primaryStage.setTitle("Delete Alert Demo");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }

}
clartaq
  • 5,320
  • 3
  • 39
  • 49
  • One problem though. The main Stage is in another class, my "Main" class. The alert is created in the Controller class. How would I call it in that method? Would I create an instance of the parent? – DevOpsSauce Nov 21 '15 at 19:13
  • Question edited to show my problem in more detail. See above ^. – DevOpsSauce Nov 21 '15 at 20:33
  • 2
    Ah. The solution is simple, but ugly. See the second answer and comments for http://stackoverflow.com/questions/11994366/how-to-reference-primarystage. You just include a method in your controller class that lets you set the primary stage. – clartaq Nov 21 '15 at 21:24
  • 2
    Or, if you don't like passing around variables, inside the event handler you can do something like: `Window owner = ((Node)event.getTarget()).getScene().getWindow();` This assumes that the Button (the event target) is in the same class as the Stage of course. – clartaq Nov 21 '15 at 21:43