How to set an additional FXML layout to an existing one

Alan :

so I have two Controllers: the MainControllerand an ImageContainerboth have a FXML layout. In my MainController i set up a SplitPane and inside of it a FlowPane now I want to load the layout of the ImageContainer in the flowpane at runtime:

PROBLEM
How do I place the layout inside the flowpane with pre filled values in textFields, set an image etc.?

Idea
ImageContainer must extend Pane, and in the MainController I have to call the constructor of the ImageContainer and add the ImageContainer to the flowpane:

ImageContainer imgC = new ImageContainer(4,2,"location");
fp_contentFlowPane.getChildren().add(imgC);

Caused by: java.lang.NullPointerException
Caused by: java.lang.reflect.InvocationTargetException

If anyone has an ideas, help is appreciated!

Code snippet Part of ImageContainer Contoller:

public class ImageContainer extends Pane {

public HBox hbx_elementContainer;
public Label lb_likeCount;
public Label lb_commentCount;
public Label lb_location;

public ImageContainer(int likeCount, int commentCount, String location) {
    this.lb_likeCount.setText(String.valueOf(likeCount));
    this.lb_commentCount.setText(String.valueOf(commentCount));
    this.lb_location.setText(location);

    Image image = new Image("/sampleFoto.JPG");
    iv_feedImage.setImage(image);

    }
}

Code snippet Part of MainController Note this is not the whole code:

public class MainScreenController{

public TextField tf_userName;
public ListView lv_listView;
public FlowPane fp_contentFlowPane;
public SplitPane sp_splitPane;

public void onItemClicked(MouseEvent mouseEvent) throws IOException {
    int index = lv_listView.getSelectionModel().getSelectedIndex();

    if (mouseEvent.getButton().equals(MouseButton.SECONDARY)) {
        if (index >= 0) {
            lv_listView.getItems().remove(index);
            userList.remove(index);
        }
    }
    else{
        //fp_contentFlowPane.getChildren().add(new 
      ImageContainer(5,5,"test"));

        ImageContainer imgC = new ImageContainer(4,2,"location");
        fp_contentFlowPane.getChildren().add(imgC);


    }
}}

Code snippet Main

public class Main extends Application {

@Override
public void start(Stage primaryStage) throws Exception{

    FXMLLoader loader = new FXMLLoader();
    loader.setLocation(getClass().getResource("/sample.fxml"));
    Parent root = loader.load();

    primaryStage.setTitle("Get Viral");
    primaryStage.setScene(new Scene(root, 1000, 700));
    primaryStage.show();
    primaryStage.getIcons().add(new Image("/iconSpectures.jpg"));

    }


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

FXML of ImageContainer:

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

<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.text.Font?>

<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" 
minWidth="-Infinity" prefHeight="200.0" prefWidth="200.0" 
xmlns="http://javafx.com/javafx/8.0.172-ea" 
xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.ImageContainer">
   <bottom>
      <HBox fx:id="hbx_elementContainer" prefHeight="31.0" prefWidth="600.0" 
    BorderPane.alignment="CENTER">
         <children>
            <Label fx:id="lb_likeCount" contentDisplay="TOP" text="Label">
               <HBox.margin>
                  <Insets right="10.0" />
               </HBox.margin></Label>
            <Label fx:id="lb_commentCount" text="Label">
               <HBox.margin>
                  <Insets right="20.0" />
               </HBox.margin></Label>
            <Label fx:id="lb_location" text="Label" />
            <Label fx:id="lb_accountHolder" text="Label" />
          <Button mnemonicParsing="false" text="Download">
               <font>
                  <Font name="Arial Bold" size="11.0" />
               </font>
               <HBox.margin>
                  <Insets right="10.0" />
               </HBox.margin>
            </Button>
         </children>
       </HBox>
   </bottom>
<center>
  <AnchorPane prefHeight="200.0" prefWidth="200.0" 
BorderPane.alignment="CENTER">
        <children>
             <ImageView fx:id="iv_feedImage" fitHeight="150.0" 
fitWidth="200.0" 
pickOnBounds="true" preserveRatio="true" AnchorPane.bottomAnchor="0.0" 
AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" 
AnchorPane.topAnchor="0.0" />
         </children>
      </AnchorPane>
   </center>
</BorderPane>
xtratic :

If you want your ImageContainer to make use of your FXML then you can simply load it in the constructor using FXMLLoader and get rid of the fx:controller="sample.ImageContainer" from your FXML.

Here's a post about when to use which method of setting a controller for an fxml file to use (fx:controller vs FXMLLoader); Because your ImageContainer constructor requires arguments, it's easier imo to use the FXMLLoader method.

public class ImageContainer extends Pane {

private static final PATH_FXML = "/internal/path/to/layout.fxml"

@FXML public HBox hbx_elementContainer;
@FXML public Label lb_likeCount;
@FXML public Label lb_commentCount;
@FXML public Label lb_location;

public ImageContainer(int likeCount, int commentCount, String location) {
    FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource(PATH_FXML));
    fxmlLoader.setRoot(this);
    fxmlLoader.setController(this);
    try {
        fxmlLoader.load();
    } catch (IOException e) {
        throw new RuntimeException(e);
    }

    this.lb_likeCount.setText(String.valueOf(likeCount));
    this.lb_commentCount.setText(String.valueOf(commentCount));
    this.lb_location.setText(location);

    Image image = new Image("/sampleFoto.JPG");
    iv_feedImage.setImage(image);
}
}

For some extra fun stuff: If you define getters and setters on a custom Control, then you can use them in the attributes of that control in FXML.

It's not exactly necessary for your use case, but you can do stuff like this.

Custom Control:

package path.to.my_package;

public class MyControl extends Control {
    private String myField;

    public String getMyField() { return myField; }
    public void setMyField(String myField) { this.myField = myField; }
}

FXML:

<?import path.to.my_package.MyControl ?>

<BorderPane xmlns="http://javafx.com/javafx/8.0.172-ea" xmlns:fx="http://javafx.com/fxml/1">
    <center>
        <MyControl myField="myValue"/>
    </center>
</BorderPane>

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=149989&siteId=1