2
votes

After much searching I found this question How to create a javafx 2.0 application MDI. What I really wanted to know is if I can create a pop-up window or child window to the main window using JavaFX components and Scene Builder to create the new window.

I ended up with this for a modal pop-up window:

In the Main class I wanted to save the primary stage to a field I can access from my primary controller class. So, I added a static variable Stage to it and this in the Main.Start() method:

primaryController.primaryStage = primaryStage;

This the method that a button in the primaryController uses:

public void OnBtnShowChild(ActionEvent event) {
    MessageBoxController msgBox = new MessageBoxController();
    try {
        msgBox.showMessageBox(primaryStage);
    } catch (Exception e) {
        e.printStackTrace(); 
    }
}

This is the MessageBoxController class that I created with help from Scene Builder. It has the basic layout of a standard pop-up box that can be used to display an Icon (ImageView), TextBox (for your message text), and two buttons (for YES/NO functionality). I am not sure yet how to have it communicate the results of what button was pressed back to the primaryController.

public class MessageBoxController implements Initializable {

@FXML
// fx:id="btnNo"
private Button btnNo; // Value injected by FXMLLoader

@FXML
// fx:id="btnYes"
private Button btnYes; // Value injected by FXMLLoader

@FXML
// fx:id="imgMessage"
private ImageView imgMessage; // Value injected by FXMLLoader

@FXML
// fx:id="txtMessage"
private TextField txtMessage; // Value injected by FXMLLoader

private Stage myParent;
private Stage messageBoxStage;

public void showMessageBox(Stage parentStage) {
    this.myParent = parentStage;

    try {
        messageBoxStage = new Stage();
        AnchorPane page = (AnchorPane) FXMLLoader.load(MessageBoxController.class.getResource("/MessageBox/MessageBoxFXML.fxml"));
        Scene scene = new Scene(page);
        messageBoxStage.setScene(scene);
        messageBoxStage.setTitle("Message Box");
        messageBoxStage.initOwner(this.myParent);
        messageBoxStage.initModality(Modality.WINDOW_MODAL);
        messageBoxStage.show();
    } catch (Exception ex) {
        System.out.println("Exception foundeth in showMessageBox");
        ex.printStackTrace();
    }
}
@Override
public void initialize(URL fxmlFileLocation, ResourceBundle arg1) {
    txtMessage.setText("Howdy");

}

public void OnBtnYes(ActionEvent event) {

}

public void OnBtnNo(ActionEvent event) {

}

}

And finally, this is the FXML file I created in Scene Builder:

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

<?import java.lang.*?>
<?import java.net.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.image.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>

<AnchorPane id="AnchorPane2" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity"   
      prefHeight="172.0" prefWidth="524.0" xmlns:fx="http://javafx.com/fxml" fx:controller="MessageBox.MessageBoxController">
  <children>
    <VBox prefHeight="172.0" prefWidth="524.0" styleClass="vboxes" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
      <children>
        <HBox alignment="CENTER" prefHeight="109.99990000000253" prefWidth="516.0" spacing="30.0">
          <children>
            <ImageView fx:id="imgMessage" fitHeight="110.0" fitWidth="146.66666666666666" pickOnBounds="true" preserveRatio="true" styleClass="null" />
            <TextField fx:id="txtMessage" editable="false" prefHeight="47.0" prefWidth="325.0" />
          </children>
          <stylesheets>
        <URL value="@MyCSS.css" />
      </stylesheets>
    </HBox>
    <HBox alignment="CENTER" prefHeight="58.0" prefWidth="516.0" spacing="30.0">
      <children>
        <Button fx:id="btnYes" mnemonicParsing="false" onAction="#OnBtnYes" text="Button" />
        <Button fx:id="btnNo" mnemonicParsing="false" onAction="#OnBtnNo" text="Button" />
      </children>
    </HBox>
  </children>
  <stylesheets>
    <URL value="@MyCSS.css" />
  </stylesheets>
</VBox>
</children>
<stylesheets>
<URL value="@MyCSS.css" />
</stylesheets>
</AnchorPane>

With this I can create a modal pop-up window, and I also want to create other child windows for displaying data in other ways using different controls. And, most importantly, I can use Scene Builder to create the layout.

What do you think? Is this a good way to do this until they add real support in Java 8 and JavaFX 8?

1
Your solution is fine. Take everything after "I ended it up with this" cut it from the question and add it as a self answer and mark the answer as correct.jewelsea
I see. I am new to Java and just learned JavaFX by taking the available tutorials and doing google searches. Info, beyond the basics, is just not there. Thus, I have no clue if what I posted is a good way to solve the problem or not, even if it seems to work. Why would no one else have thought of this if it is a good solution? All I found were other very convoluted things that did not use JavaFX.Rick Falck
Most JavaFX message box solutions are just plain Java code rather than using FXML for the layout. I filed a documentation request RT-27567 Create an official tutorial on how to create Common Application Dialogs.jewelsea
Actually, the above solution does NOT work. The problem is the FXMLLoader static method builds the root control from the FXML file and creates a new instance of the controller class within its processing, and there's no way to get it. I just separated the controller class from the creation of it. Now it works like a modal dialog, and you can get the result of what button was pressed.Rick Falck
Post your corrected solution as an answer - sharing knowledge is what the site is for. See Should I not answer my own questions?.jewelsea

1 Answers

2
votes

did you try wit the Group class? you can add diferent elements with fxml and controllers.

Group root= new Group(); 
AnchorPane frame=FXMLLoader.load(getClass().getResource("frame.fxml"));
AnchorPane  content=  FXMLLoader.load(getClass().getResource("principal.fxml"));
root.getChildren().add(window);
root.getChildren().add(frame);
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();