-1

Hy guys, I'm developing an application using javafx and fxml. What I'm currently trying to do is to update a flowpane, adding components to it when the user performs an action (is not the case but let's take as an example the click of a button).

Let's suppose that the method just has to add buttons with the passed labels to the flowpane.

In the Controller of the fxml that contains the flowpane I have this:

public class CategoryPaneController implements Initializable {
    @FXML
    private FlowPane categoryContainer;
    
    public void setCategories(String[] labels) throws IOException{
        for(String label : labels){
            Button button = new Button(label);
            categoryContainer.getChildren().add(button);
        }
    }
}

This method is called in another controller as follows:

public class AddCategoryController implements Initializable {

@FXML
private Pane addCategoryPane;

@Override
public void initialize(URL url, ResourceBundle rb) {
    // TODO
}    

@FXML
private void refreshCategories(ActionEvent event) throws IOException {
    FXMLLoader loader = new FXMLLoader(getClass().getResource("/view/categoryPane.fxml"));
    loader.load();
    CategoryPaneController cat = loader.getController();
    String[] labels = {"categoria3", "categoria4"};
    cat.setCategories(labels);
}

}

The categoryPane.fxml is the following:

<ScrollPane fx:id="storeMainPane" fx:controller="controller.CategoryPaneController">
   <content>
      <VBox prefHeight="629.0" prefWidth="862.0">
         <children>
            <Label alignment="TOP_CENTER" contentDisplay="CENTER" prefHeight="68.0" prefWidth="857.0" text="Magazzino" />
            <FlowPane fx:id="categoryContainer" prefHeight="549.0" prefWidth="862.0" />
         </children>
      </VBox>
   </content>
</ScrollPane>

And the following is the addCategory.fxml file

<Pane fx:id="addCategoryPane"  fx:controller="controller.AddCategoryController">
   <children>
      <Button onAction="#refreshCategories" text="aggiungi categoria" />
   </children>
</Pane>

I've debbugged the code and the method is called in the right way, it adds the buttons to the flowpane but the latter doesn't change.

Thanks in advance. <3

NaN
  • 1
  • 1
  • 2
    There is nothing wrong with the code you posted; the errors lie elsewhere. Create and post a [mre]; i.e. a simple *but complete* example that does nothing other than what you describe (adds a couple of components to a `FlowPane` on the click of a button). – James_D Jul 05 '22 at 19:23
  • 2
    Make sure this is reproducible via copy/paste with no change or addition. – jewelsea Jul 05 '22 at 19:23
  • 2
    Without a *complete* example that can be copied, pasted, and run with no further code, it's impossible to completely diagnose the problem. However, in your `refreshCategories()` method, you load `categoryPane.fxml` and make some modifications to it via a call to its controller's `setCategories()` method. However, since you never actually display the FXML anywhere, it's not clear what you expect to see from this. – James_D Jul 05 '22 at 19:57
  • Probably you need to store a reference to the originally loaded categoryPane controller and set the categories on that rather than load new FXML which will generate a new Controller instance and new nodes. Or you can use [MVC](https://stackoverflow.com/questions/32342864/applying-mvc-with-javafx). – jewelsea Jul 05 '22 at 21:16
  • 1
    As an aside, when using most of the built-in layout panes, don't hardcode sizes by setting prefHeight and prefWidth of contained nodes like labels, let the layout panes work out the sizing, that is what they are for. – jewelsea Jul 05 '22 at 21:19
  • 1
    thanks for the comments, and the advice; what I was doing wrong, as @jewelsea pointed out, was the invocation of the method `setCategories()` on a new Controller, not the one linked to the node I was viewing. Solved it through the use of a singleton class (that manages the communication between existing controllers). – NaN Jul 06 '22 at 19:35

1 Answers1

0

Every time you load a new FXML a new Controller instance and new nodes will be generated.

If you want to use an existing controller and nodes, you need to store a reference to the originally loaded controller and invoke methods on that.

Or you can use MVC:

jewelsea
  • 150,031
  • 14
  • 366
  • 406