0

I'm new in the javafx and until now is going good. But I don't find any form to send a object from a screen to another. I have some dificult to understand funciont od annotations @FXML and the method initialize from Initializable interface

Class that calls another

public class FluxoCaixaController extends ParametrosTelas implements iTelaPrincipalFX {
    /*Atributos locais*/

    private ObservableList<String> opcoes = FXCollections.observableArrayList("Receita", "Despesa");
    private Object parent;
    private AberturaDeTelasFX formaAbertura;
    private ToggleGroup modalGroup = new ToggleGroup();
    private Categoria categoria;
    private CategoriaTreeViewController root = new CategoriaTreeViewController();


    @Override
    public void showScreen() {
        formaAbertura = new AberturaDialogFX();
        formaAbertura.loadFXML(bundle, icone, bundle.getString("screnn.fluxo.title"), new AnchorPane(), "FluxoCaixa.fxml");        
    }

    @Override // This method is called by the FXMLLoader when initialization is complete
    public void initialize(URL fxmlFileLocation, ResourceBundle resources) {
        tipoField.getItems().setAll(opcoes);
        root.setParentController(getInstance());
        //idColumn.setCellValueFactory(new PropertyValueFactory<>("id"));
        //descricaoColumn.setCellValueFactory(new PropertyValueFactory<>("descricao"));
        //atualizaTabela();
    }

    @FXML
    private void btnAddCetegoria() {                
        root.showScreen();
        categoriaSubcategoriaField.setText(categoria.getDescricao());
    }

    private Object getInstance(){
        return this;      

}

Class called

public class CategoriaTreeViewController extends ParametrosTelas implements iTelaNormalFX {

    private AberturaDeTelasFX formaAbertura;
    private Object parent;
    private CategoriaService categoriaService = new CategoriaService();
    @FXML
    private TreeView<Categoria> treeView;
    private Categoria EmptyCategoria;
    private TreeItem<Categoria> rootItem;
    private EventHandler<MouseEvent> mouseEventHandle;

    @Override
    public void showScreen() {        
        formaAbertura = new AberturaDialogFX();
        formaAbertura.loadFXML(bundle, icone, bundle.getString("screnn.subcategory.title"), new AnchorPane(), "CategoriaTreeView.fxml");
    }

    @Override // This method is called by the FXMLLoader when initialization is complete
    public void initialize(URL fxmlFileLocation, ResourceBundle resources) {
        initialiazeTree();
        mouseEventHandle = (MouseEvent event) -> {
            handleMouseClicked(event);
        };
        treeView.addEventHandler(MouseEvent.MOUSE_CLICKED, mouseEventHandle);
        treeView.setRoot(rootItem);        
    }

    private void initialiazeTree() {
        EmptyCategoria = new Categoria();
        EmptyCategoria.setDescricao("Categorias");
        rootItem = new TreeItem<>(EmptyCategoria);
        // private TreeItem<SubCategoria> itens = new TreeItem<>();
        for (Categoria g : categoriaService.listaCategorias()) {
            List<Categoria> subLst = categoriaService.listaSubCategoriasByCategoria(g.getId());
            TreeItem<Categoria> itens = new TreeItem<>(g);
            //ObservableList<Categoria> subData = FXCollections.observableArrayList(subLst);
            for (Categoria s : subLst) {
                s.setCategoria(g);
                TreeItem<Categoria> subItem = new TreeItem<>(s);
                //subItem.addEventHandler(MouseEvent, new EventHandler<MouseEvent>() {                

                itens.getChildren().add(subItem);
            }

            //itens.getChildren().add(itens);
            rootItem.getChildren().add(itens);
        }
    }

    private void handleMouseClicked(MouseEvent event) {
        if (treeView.getSelectionModel().getSelectedItem() != null) {
            Categoria name = (Categoria) ((TreeItem) treeView.getSelectionModel().getSelectedItem()).getValue();
            FluxoCaixaController fluxo = (FluxoCaixaController) getParentController();
            fluxo.setCategoria(name);
            System.out.println("Node click: " + name.getDescricao());
            formaAbertura.getStage().hide();
        }
        /*Node node = event.getPickResult().getIntersectedNode();
         // Accept clicks only on node cells, and not on empty spaces of the TreeView
         if (node instanceof Text || (node instanceof TreeCell && ((TreeCell) node).getText() != null)) {
         String name = (String) ((TreeItem)treeView.getSelectionModel().getSelectedItem()).getValue();
         System.out.println("Node click: " + name);
         }*/
    }


}

Must of the interfaces just point to on or two methods. The AberturaDeTelasFX interface has a Implementation that says how the screen should open.

AberturaNormalFX

public class AberturaNormalFX implements AberturaDeTelasFX {

    private Stage stage;

    @Override
    public void loadFXML(ResourceBundle bundle, Image icon, String title, Node node, String fxmlPath) {
        try {
            // Carrega o root layout do arquivo fxml.
            FXMLLoader loader = new FXMLLoader();
            loader.setLocation(getClass()
                    .getResource(fxmlPath));
            loader.setResources(bundle);
            if (node instanceof BorderPane) {
                BorderPane rootLayout = (BorderPane) loader.load();
                showLayout(icon, title, rootLayout);
            } else if (node instanceof AnchorPane) {
                AnchorPane rootLayout = (AnchorPane) loader.load();
                showLayout(icon, title, rootLayout);
            }

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

    private void showLayout(Image icone, String title, Parent node) {
        stage = new Stage();
        Scene scene = new Scene(node);
        stage.setTitle(title);
        stage.getIcons().add(icone);
        stage.setScene(scene);

        stage.show();
    }

    @Override
    public void loadFXML(String title, Node node, String fxmlPath) {
        throw new UnsupportedOperationException("Not supported yet."); //To chan

ge body of generated methods, choose Tools | Templates. }

/**
 * @return the stage
 */
@Override
public Stage getStage() {
    return stage;
}

}

Krismorte
  • 642
  • 7
  • 24
  • Start by reading the documentation of the [Screen](http://docs.oracle.com/javase/8/javafx/api/javafx/stage/Screen.html) class. – VGR Feb 23 '16 at 21:42
  • @VGR I put the class that shows the UI. I say Screen but I mean the UI – Krismorte Feb 23 '16 at 22:07
  • Probable duplicate of http://stackoverflow.com/questions/14187963/passing-parameters-javafx-fxml/14190310#14190310 – James_D Feb 23 '16 at 23:03
  • I see that my problem was the was with interface Initializable. Now I can send a object, but I have to initializa every single Object. – Krismorte Feb 23 '16 at 23:41

1 Answers1

0

Looking on your code I did not find a class, which extends Application. In my project, which I built recently, I used it as a part of the Presentation layer, kind of a bridge between controllers (which represent Controller layer), where each controller manages a single screen. Consider following example:

public class MainAppFX extends Application {

// The primary window or frame of this application
private Stage primaryStage;

this 'patient' represents object from your controller:

private PatientData patient; 

/**
 * Default constructor
 */
public MainAppFX() {
    super();
}

/**
 * The application starts here
 *
 * @param primaryStage
 * @throws Exception
 */
@Override
public void start(Stage primaryStage) throws Exception {

    log.info("Program loads");

    // The Stage comes from the framework so make a copy to use elsewhere
    this.primaryStage = primaryStage;
    // Create the Scene and put it on the Stage
    loadPatientParentWindow();

    // Set the window title
    this.primaryStage.setTitle("Your Window title");

    this.primaryStage.show();
}

/**
 * Loads Patient FXML layout
 * This method loads one of your screens
 */
public void loadPatientParentWindow() {

    try {

        // Instantiate the FXMLLoader
        FXMLLoader loader = new FXMLLoader();
        // Set the location of the fxml file in the FXMLLoader
    loader.setLocation(MainAppFX.class.getResource("/fxml/PatientForm.fxml"));

        // Parent is the base class for all nodes that have children in the
        // scene graph such as AnchorPane and most other containers
        Parent parent = (AnchorPane) loader.load();

        // Load the parent into a Scene
        Scene scene = new Scene(parent);

        // Put the Scene on Stage
        primaryStage.setScene(scene);

        // Give the PatientFXMLController controller access to the main app.
        PatientFXMLController controller = loader.getController();

below is the setter method of Patient controller, where it gets an access to the Main class

        controller.setMainAppFX(this); 

    } catch (IOException | SQLException ex) { // getting resources or files could fail
        log.error(null, ex);
        System.exit(1);
    }
}


/**
 * Setter for PatientData object in the Main class

you use it in the controller class

 *
 * @param patient
 */
public void setPatient(PatientData patient) {
    this.patient = patient;
}

/**
 * Getting PatientData object from the Main class
 *
 * @return
 */
public PatientData getPatient() {
    return patient;
}

/**
 * Where it all begins
 *
 * @param args command line arguments
 */
public static void main(String[] args) {
    launch(args);
    System.exit(0);
}

}

And here is one of the controller classes, which represent one of the screens:

public class PatientFXMLController {

Reference to the main application starts here

private MainAppFX mainApp;

Next object you will be passing to the main class using setters

private PatientData patient;

// The @FXML annotation on a class variable results in the matching
// reference being injected into the variable
// label is defined in the fxml file
// Bunch of @FXML annotations with respective fields (you can get them from SceneBuilder)
@FXML
private TextField patientIdField;
@FXML
private TextField lastNameField;
// so on...


/**
 * The constructor. The constructor is called before the initialize()
 * method. You don't need to call it. It's being called by automatically
 */
public PatientFXMLController() {
    super();

Create empty Patient object for initialize method

    patient = new PatientData();
}

/**
 * Initializes the controller class. This method is automatically called
 * after the fxml file has been loaded. Useful if a control must be
 * dynamically configured such as loading data into a table.
 */
@FXML
private void initialize() {
    log.info("initialize called");

    // Initializing form fields
    Bindings.bindBidirectional(patientIdField.textProperty(), patient.patientIdProperty(), new NumberStringConverter());
    // so on .....
}

/**
 * Loads Another screen

this method below represents an action for a button, which leads to another screen, and where you passing an object from this controller to the main class. And then you can pass this object from main class to anotherScreen controller, since you will have its loadAnotherScreenWindow() method there

 *
 * @param event
 */
@FXML
private void loadAnotherScreen(ActionEvent event) throws SQLException {

Passing Patient object to the main class so it can be used in Another screen controller to get related inpatients

    mainApp.setPatient(patient);
}


/**
 * Is called by the main application to give a reference back to itself.
 * This class receives the reference of the main class.
 *
 * @param mainApp
 */
public void setMainAppFX(MainAppFX mainApp) {
    this.mainApp = mainApp;
}

/**
 * Setter for PatientData object
 *
 * @param patient
 */
public void setPatient(PatientData patient) {
    this.patient = patient;
}

}
Mykola
  • 352
  • 1
  • 9