-1

Controller of the father class

this class contains 3 button 'btnSocieta', 'btnUnitaLocali', 'btnReparti'. The first is enable from default other 2 are disable. In the stackPane i show the start page where you can find right away.

they have to change state after calling method setEnableBtnUnitaLocale or the other one

package View.Controllers;

import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;

import com.jfoenix.controls.JFXButton;

import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class Creazione implements Initializable {

    @FXML
    private JFXButton btnSocieta;

    @FXML
    private JFXButton btnUnitaLocali;

    @FXML
    private JFXButton btnReparti;

    @FXML
    private StackPane stackPane;

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

        btnUnitaLocali.setDisable(true);
        btnReparti.setDisable(true);

        try {
            Parent root = FXMLLoader.load(getClass().getResource("/View/fxml/creazione_societa.fxml"));
            stackPane.getChildren().removeAll();
            stackPane.getChildren().setAll(root);

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public void switchToSocieta(javafx.event.ActionEvent event) throws IOException {
        Parent root = FXMLLoader.load(getClass().getResource("/View/fxml/creazione_societa.fxml"));
        stackPane.getChildren().removeAll();
        stackPane.getChildren().setAll(root);
    }

    public void switchToUnitaLocali(javafx.event.ActionEvent event) throws IOException {
        Parent root = FXMLLoader.load(getClass().getResource("/View/fxml/creazione_unitalocale.fxml"));
        stackPane.getChildren().removeAll();
        stackPane.getChildren().setAll(root);
    }

    public void switchToReparti(javafx.event.ActionEvent event) {
        System.out.println("You clicked me!");
    }

    public void setEnableBtnUnitaLocale() {
        
        btnUnitaLocali.setDisable(false);
        System.out.println("setEnableBtnUnitaLocale()");

    }

    public void setEnableBtnReparti() {

        btnReparti.setDisable(false);
    }

}

FXML file menaged by Creazione that have a StackPane that contains CreazioneSocieta


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

<?import com.jfoenix.controls.JFXButton?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.layout.StackPane?>

<BorderPane xmlns="http://javafx.com/javafx/20.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="View.Controllers.Creazione">
   <top>
      <Pane prefHeight="48.0" prefWidth="600.0" BorderPane.alignment="CENTER">
         <children>
            <Label alignment="CENTER" layoutX="181.0" layoutY="16.0" minWidth="34.0" prefHeight="17.0" text="&gt;&gt;" />
            <Label alignment="CENTER" layoutX="382.0" layoutY="16.0" text="&gt;&gt;" />
            <JFXButton fx:id="btnSocieta" alignment="CENTER" layoutX="53.0" layoutY="12.0" onAction="#switchToSocieta" text="Società / Ente" />
            <JFXButton fx:id="btnUnitaLocali" alignment="CENTER" layoutX="255.0" layoutY="12.0" onAction="#switchToUnitaLocali" text="Unità locali" />
            <JFXButton fx:id="btnReparti" alignment="CENTER" layoutX="453.0" layoutY="12.0" onAction="#switchToReparti" text="Reparti" />
         </children>
      </Pane>
   </top>
   <center>
      <StackPane fx:id="stackPane" prefHeight="352.0" prefWidth="600.0" BorderPane.alignment="CENTER" />
   </center>
</BorderPane>

Controller of the FXML file

this controller only scope is to call the method 'setEnableBtnUnitaLocale' that we've see before through method 'salvaSocieta'

package View.Controllers;

import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;

import com.jfoenix.controls.JFXButton;

import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;


public class CreazioneSocieta implements Initializable {

    @FXML
    JFXButton btnSalva;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        

    }

    public void salvaSocieta(javafx.event.ActionEvent event) throws IOException{
        
        FXMLLoader loader = new FXMLLoader(getClass().getResource("/View/fxml/main_creazione.fxml"));
        Parent root = (Parent) loader.load();
        
        Creazione controller = loader.getController();
        controller.setEnableBtnUnitaLocale();

    }
    
}

FXML File that contains the save button

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

<?import com.jfoenix.controls.JFXButton?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.Pane?>

<Pane xmlns="http://javafx.com/javafx/20.0.1" xmlns:fx="http://javafx.com/fxml/1"
   fx:controller="View.Controllers.CreazioneSocieta">
   <children>
      <Label layoutX="51.0" layoutY="139.0" prefHeight="17.0" prefWidth="93.0"
         text="Ragione Sociale:" />
      <TextField layoutX="153.0" layoutY="135.0" prefHeight="25.0" prefWidth="437.0" />
      <Label layoutX="51.0" layoutY="203.0" prefHeight="17.0" prefWidth="56.0" text="Indirizzo:" />
      <TextField layoutX="115.0" layoutY="199.0" prefHeight="25.0" prefWidth="330.0" />
      <Label layoutX="51.0" layoutY="324.0" prefHeight="17.0" prefWidth="56.0" text="Telefono:" />
      <TextField accessibleText="INTEGER" layoutX="115.0" layoutY="320.0" prefHeight="25.0"
         prefWidth="330.0" />
      <Label layoutX="51.0" layoutY="262.0" prefHeight="17.0" prefWidth="43.0" text="e-mail:" />
      <TextField layoutX="115.0" layoutY="258.0" prefHeight="25.0" prefWidth="330.0" />
      <Label layoutX="467.0" layoutY="203.0" prefHeight="17.0" prefWidth="56.0" text="Provincia:" />
      <TextField accessibleText="INTEGER" layoutX="533.0" layoutY="199.0" prefHeight="25.0"
         prefWidth="56.0" />
      <JFXButton onAction="#salvaSocieta" contentDisplay="CENTER" defaultButton="true"
         graphicTextGap="0.0" layoutX="573.0" layoutY="421.0" prefHeight="45.0" prefWidth="0.0"
         ripplerFill="#bfbdbd" textFill="WHITE" textOverrun="CLIP">
         <graphic>
            <ImageView fitHeight="37.0" fitWidth="37.0" pickOnBounds="true" preserveRatio="true">
               <image>
                  <Image url="@../icons/save_icon.png" />
               </image>
            </ImageView>
         </graphic>
      </JFXButton>
   </children>
</Pane>

Problem: The 'btnUnitaLocale' doesn't became enable after calling the function 'setEnableBtnUnitaLocale'

3
  • It's not really clear what you're doing in the salvaSocieta(...) method. You load the main_creazione.fxml file, and call a method on its controller, but since you never actually do anything with the UI you loaded (i.e. you just put it in the variable root, and then do nothing) you obviously won't see the result of calling the controller method anywhere.
    – James_D
    Commented Oct 9, 2023 at 16:41
  • i don't really know ho to call the method from a class to an other without creating a new Object of the Creazione class
    – Flavio
    Commented Oct 9, 2023 at 16:50
  • The "quick and dirty" approach would just be to pass a reference to the existing Creazione instance to the CreazioneSocieta controller instance that is created when you load creazione_societa.fxml. But really here you should use a MVC (or similar) design
    – James_D
    Commented Oct 9, 2023 at 16:58

2 Answers 2

2

Use a MVC approach. Define a Model class that contains the state of the application, with mechanisms to observe the values and respond to them changes. You can use JavaFX Properties to do this easily (see this or the "Bindings and Observable Values" section of this, and links from there)

public class Model {

    private final BooleanProperty societySaved = new SimpleBooleanProperty(false);

    public BooleanProperty societySavedProperty() {
        return societySaved ;
    }

    public final boolean isSocietySaved() {
        return societySavedProperty().get();
    }

    public final void setSocietySaved(boolean societySaved) {
        societySavedProperty().set(societySaved);
    }


    // similarly for other properties as needed
}

In your Creazione controller class, define a field for the model and bind the state of the button to the state in the model:

public class Creazione {

    @FXML
    private JFXButton btnSocieta;

    @FXML
    private JFXButton btnUnitaLocali;

    @FXML
    private JFXButton btnReparti;

    @FXML
    private StackPane stackPane;

    private Model model ;

    public void setModel(Model model) {
        this.model = model ;
        btnUnitaLocali.disableProperty().bind(model.societySavedProperty().not());
        // similarly for other buttons and properties in the model
    }

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

        //btnUnitaLocali.setDisable(true);
        //btnReparti.setDisable(true);

        try {
            Parent root = FXMLLoader.load(getClass().getResource("/View/fxml/creazione_societa.fxml"));
            stackPane.getChildren().removeAll();
            stackPane.getChildren().setAll(root);

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    // ... (further modifications to methods shown later)



    // these are not needed
    // public void setEnableBtnUnitaLocale() {
        
    //     btnUnitaLocali.setDisable(false);
    //     System.out.println("setEnableBtnUnitaLocale()");

    // }

    // public void setEnableBtnReparti() {

    //     btnReparti.setDisable(false);
    // }

}

Similarly, in your other controllers, define a reference to the model and update the property. For example:

public class CreazioneSocieta  {

    private Model model ;

    public void setModel(Model model) {
        this.model = model;
    }


    public void salvaSocieta(ActionEvent event) {
        
        model.setSocietySaved(true);

    }
    
}

Now, in your application code, you need to create a Model instance and when you load the initial view, pass the model to the controller:

Model model = new Model();
FXMLLoader loader = new FXMLLoader(getClass().getResource("/View/fxml/main_creazione.fxml"));
Parent root = (Parent) loader.load();
        
Creazione controller = loader.getController();
controller.setModel(model);

Scene scene = new Scene(root);
stage.setScene(scene);
// etc.

Finally, back in your Creazione class, be sure to pass the same model instance to the other controllers. For example:

public class Creazione {

    // existing code ...

    public void switchToSocieta(javafx.event.ActionEvent event) throws IOException {
        FXMLLoader loader = new FXMLLoader(getClass().getResource("/View/fxml/creazione_societa.fxml"));
        Parent root = loader.load();
        CreazioneSocieta controller = loader.getController();
        controller.setModel(model);

        stackPane.getChildren().removeAll();
        stackPane.getChildren().setAll(root);
    }
}

For better decoupling of the controllers, in particular in the context of switching scene, study this example.

1
  • can you pls review my latest answer ty so much for your correction but there is a little problem that i couldn't solve if not like that
    – Flavio
    Commented Oct 10, 2023 at 19:12
-1

I ended up doing this:

This is the method you can find in ViewController

public void switchToCreazione(ActionEvent event) throws IOException{
    CreazioneModel creazioneModel = new CreazioneModel();

    FXMLLoader loader = 
  new FXMLLoader(getClass().getResource("/View/fxml/main_creazione.fxml"));

    Parent root = loader.load();
    Creazione creazione = loader.getController();

    creazione.setCreazioneModel(creazioneModel);

    stackPane.getChildren().removeAll();
    stackPane.getChildren().setAll(root);
}

This is the method you can find in the preview answer

public void setCreazioneModel(CreazioneModel creazioneModel) {
    this.creazioneModel = creazioneModel;

    try {
        switchToSocieta();
    } catch (IOException e) {
        e.printStackTrace();
    }
    
    this.btnUnitaLocali
        .disableProperty()
        .bind(creazioneModel.societaSavedProperty().not());
    this.btnReparti
        .disableProperty()
        .bind(creazioneModel.unitaLocaleSavedProperty().not());}

This is the method setModel in CreazioneModel class

public void setCreazioneModel(CreazioneModel creazioneModel) {
    this.creazioneModel = creazioneModel;

    try {
        switchToSocieta();
    } catch (IOException e) {
        e.printStackTrace();
    }
    
    this.btnUnitaLocali
        .disableProperty()
        .bind(creazioneModel.societaSavedProperty().not());
    this.btnReparti
        .disableProperty()
        .bind(creazioneModel.unitaLocaleSavedProperty().not());}

Warning

i couldn't call switchToSocieta in the initialize method of Creazione because it wont have the Model correctly initialized

1
  • 1
    Creating a new model instance is almost certainly an error.
    – James_D
    Commented Oct 10, 2023 at 19:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.