3

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?

Community
  • 1
  • 1
Rick Falck
  • 1,778
  • 3
  • 15
  • 19
  • 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 May 03 '13 at 01:21
  • 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 May 03 '13 at 03:03
  • Most [JavaFX message box solutions](http://stackoverflow.com/questions/11662857/javafx-2-1-messagebox) 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](https://javafx-jira.kenai.com/browse/RT-27567). – jewelsea May 03 '13 at 05:00
  • 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 May 03 '13 at 06:25
  • I did get it to work, but as you said earlier, it wouldn't be asking a question to post my solution. I would just be doing it to share what I did. I chose this site because it pops up a lot in google searches, and I couldn't find a better place for it. What would you suggest I do with it? Thanks. – Rick Falck May 03 '13 at 06:29
  • 2
    Post your corrected solution as an answer - sharing knowledge is what the site is for. See [Should I not answer my own questions?](http://meta.stackexchange.com/questions/12513/should-i-not-answer-my-own-questions). – jewelsea May 03 '13 at 08:11
  • Consider that you can [get a controller](http://docs.oracle.com/javafx/2/api/javafx/fxml/FXMLLoader.html#getController()) from an `FXMLLoader` if you [instantiate](http://docs.oracle.com/javafx/2/api/javafx/fxml/FXMLLoader.html#FXMLLoader(java.net.URL)) it and load using the non-static [load()](http://docs.oracle.com/javafx/2/api/javafx/fxml/FXMLLoader.html#load()) method, it probably doesn't help you though and likely you still need to perform the controller instantiation externally from the controller code. – jewelsea May 03 '13 at 08:22
  • Also consider [showAndWait()](http://docs.oracle.com/javafx/2/api/javafx/stage/Stage.html#showAndWait()) `Shows this stage and waits for it to be hidden (closed) before returning to the caller` for the message box stage rather than `show()` if you want the request to show the dialog and get a result from it to appear synchronous to the calling code. – jewelsea May 03 '13 at 08:24

1 Answers1

2

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();
Csharls
  • 550
  • 8
  • 19