1

I am writing an app where I need the same custom popup window to appear when different buttons are clicked. Right now the popup is just a simple "Are You Sure? OK/Cancel" window, but later it will expand to include more customized features... so I can't use the quickie Dialog built-ins.

Here's the weird thing. When Button X is pushed, the popUp (defined in FXML) launches just fine, but my controller class doesn't seem to be running. I didn't think that you could do that. What I can't figure out is why the controller isn't running. I would have thought the app would crash if the controller wasn't working.

Here' the code a button will call to launch the popup:

private void popUpLaunch(Button caller){
    Stage popUpStage = new Stage();
    Parent root;

    try {
        root = FXMLLoader.load(getClass().getResource("popUp1.fxml"));
        popUpStage.setScene(new Scene(root));
        popUpStage.initModality(Modality.APPLICATION_MODAL);    // popup
        popUpStage.initOwner(caller.getScene().getWindow());
        popUpStage.showAndWait();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

All of that works great. Here's the complete FXML, /src/sl/view/popUp1.fxml:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Font?>
<?import javafx.scene.text.Text?>

<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="130.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sl.view.PopUp1Controller">
   <children>
      <Text fx:id="popUpMessageText" layoutX="14.0" layoutY="14.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Message Goes Here" textAlignment="CENTER" wrappingWidth="577.6708984375" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
         <font>
            <Font size="38.0" />
         </font>
      </Text>
      <Button fx:id="btnPopUpOK" layoutX="126.0" layoutY="68.0" mnemonicParsing="false" prefHeight="31.0" prefWidth="157.0" text="OK" />
      <Button fx:id="btnPopUpCancel" layoutX="286.0" layoutY="68.0" mnemonicParsing="false" prefHeight="31.0" prefWidth="169.0" text="Cancel" />
   </children>
</AnchorPane>

The window loads just fine. And finally, here's the complete controller, /src/sl/view/PopUp1Controller.java:

package sl.view;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.text.Text;
import javafx.stage.Stage;

public class PopUp1Controller {
    @FXML Text  popUpMessageText;
    @FXML Button    btnPopUpOK;
    @FXML Button    btnPopUpCancel;
    Stage stage;

    public void start(Stage stage) throws Exception{
        System.out.println("Popup controller launched!");   // never reach this... so the controller is not launching???
        this.stage = stage;
        popUpMessageText.setText("Interesting message here!");
        btnPopUpOK.setOnAction(event -> {
            System.out.println("You cliced OK...");
        });
        btnPopUpCancel.setOnAction(event -> {
            System.out.println("You cliced Cancel");
            stage.close();
        });
    }
}

Some thoughts...

I used SceneBuilder to generate the FXML. When I assigned the Controller Class for that AnchorPane, I picked "sl.view.PopUp1Controller" from the drop-down menu. So I'm pretty sure that's right.

Also: I've looked through the other "JavaFX Popup" posts, but I don't see one that specifically addresses my issue. A lot of post are like the below post which are basically, "Why not use these other popup options rather than re-invent the wheel?" e.g.: JavaFX 2 custom popup pane In my case, I do want to reinvent the wheel, because I need my popups to carry more-then-usual functionality, they will not be simple dialog boxes.

Pete
  • 1,511
  • 2
  • 26
  • 49
  • The `start()` method is never called in the controller (why do you expect it to be called?). Just put the code in a method called `initialize()` (with no arguments). See the [documentation](https://docs.oracle.com/javase/9/docs/api/javafx/fxml/doc-files/introduction_to_fxml.html#controllers). Also note that the built-in dialogs almost certainly can do what you want, as you can set an arbitrary node as their [content](https://docs.oracle.com/javase/9/docs/api/javafx/scene/control/DialogPane.html#contentProperty). – James_D Dec 21 '17 at 19:00

1 Answers1

2

If you want code in a controller to execute when the controller is initialized, put it in the initialize() method (see the documentation):

public class PopUp1Controller {
    @FXML Text  popUpMessageText;
    @FXML Button    btnPopUpOK;
    @FXML Button    btnPopUpCancel;

    public void initialize() {
        System.out.println("Popup controller launched!");   // never reach this... so the controller is not launching???
        popUpMessageText.setText("Interesting message here!");
        btnPopUpOK.setOnAction(event -> {
            System.out.println("You cliced OK...");
        });
        btnPopUpCancel.setOnAction(event -> {
            System.out.println("You cliced Cancel");
            btnPopupCancel.getScene().getWindow().hide();
        });
    }
}
James_D
  • 201,275
  • 16
  • 291
  • 322
  • Awesome, that worked like a charm. And thanks for pointing out the documentation. I am taking a class on Java apps, and the prof never mentioned this source. I love a good read. – Pete Dec 21 '17 at 20:18