4

I want to click a column and send the cell index to a new stage. But I can't pass my parameter (int clickIndex) to another controller EditClientController. I've tried everything, but it still does not work.

MainController

package controller;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.input.MouseEvent;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.util.Callback;
import model.Table;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;

public class MainController implements Initializable {

    @FXML
    TableView<Table> tableID;
    @FXML
    TableColumn iLp;
    @FXML
    TableColumn iCity;
    @FXML
    TableColumn iDeviceName;
    @FXML
    TableColumn iSerialNumber;
    @FXML
    TableColumn iCompanyName;
    @FXML
    TableColumn iContact;
    @FXML
    TableColumn iSellDate;
    @FXML
    TableColumn iWarranty;
    @FXML
    TableColumn iNextReview;
    @FXML
    TableColumn iWarrantyTrue;
    @FXML
    Button addButton;
    @FXML
    ComboBox warrantyLength;
    @FXML
    ComboBox nextReview;
    @FXML
    ComboBox warrantyTrue;


    //Define variables
    private int iNumber= 1;
    public int clickIndex;


    //Create table data
     ObservableList<Table> data = FXCollections.observableArrayList();

    //Combo box
    final ObservableList warranty = FXCollections.observableArrayList("---",12,24,36);
    final ObservableList review = FXCollections.observableArrayList("---","tydzień","miesiąc","2 miesiące", "6 miesięcy");
    final ObservableList warrantyTF = FXCollections.observableArrayList("---","tak","nie");



    Callback<TableColumn, TableCell> cellFactory2 =
            new Callback<TableColumn, TableCell>() {
                public TableCell call(TableColumn p) {

                    final TableCell cell = new TableCell<Table, Integer>() {
                        @Override
                        public void updateItem(Integer item, boolean empty) {
                            super.updateItem(item, empty);
                            setText(empty ? null : getString());
                            setGraphic(null);
                        }

                        private String getString() {
                            return getItem() == null ? "" : getItem().toString();
                        }
                    };

                    cell.addEventFilter(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
                        @Override
                        public void handle(MouseEvent event) {
                            if (event.getClickCount() > 1) {
                                clickIndex=cell.getIndex();
                                try {
                                    FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("editClient.fxml"));
                                    Parent root1 = (Parent) fxmlLoader.load();
                                    Stage stage = new Stage();
                                    stage.setTitle("Edytuj klienta");
                                    stage.setScene(new Scene(root1));
                                    stage.show();
                                } catch(Exception e) {
                                    e.printStackTrace();
                                }
                            }
                        }
                    });
                    return cell;
                }
            };

    Callback<TableColumn, TableCell> cellFactory =
            new Callback<TableColumn, TableCell>() {
                public TableCell call(TableColumn p) {

                    final TableCell cell = new TableCell<Table, String>() {
                        private Text text;
                        @Override
                        public void updateItem(String item, boolean empty) {
                            super.updateItem(item, empty);
                            text = new Text(item);
                            text.setWrappingWidth(100);
                            setGraphic(text);
                        }

                        private String getString() {
                            return getItem() == null ? "" : getItem().toString();
                        }
                    };

                    cell.addEventFilter(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
                        @Override
                        public void handle(MouseEvent event) {
                            if (event.getClickCount() > 1) {
                                clickIndex = cell.getIndex();
                                try {
                                    FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("editClient.fxml"));
                                    Parent root1 = (Parent) fxmlLoader.load();
                                    Stage stage = new Stage();
                                    stage.setTitle("Edytuj klienta");
                                    stage.setScene(new Scene(root1));
                                    stage.show();
                                } catch(Exception e) {
                                    e.printStackTrace();
                                }
                            }
                        }
                    });
                    return cell;
                }
            };

    public void setClickedIndex(int click){
        this.clickIndex=click;
    }

    public int getClickIndex(){
        return clickIndex;
    }


    //Plik
    public void openFile() {
        FileReader plik = null;
        int tab0=1;
        int tab7=0;
        String tab9=null;
        try {
            plik = new FileReader("dane.txt");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        BufferedReader bfr = new BufferedReader(plik);
        String linia = null;

        try {
            while ((linia = bfr.readLine()) != null) {
                String[] tab = linia.split(";");
                tab7=Integer.parseInt(tab[7]);
                if(tab.length==10) {
                    if(tab[9].contains(tab[8])){
                        tab9="Tak";
                    }else{
                        tab9="Nie";
                    }
                }
                Table tablica = new Table(tab0++, tab[1], tab[2], tab[3], tab[4], tab[5], tab[6], tab7, tab[8], tab9);
                data.add(tablica);

            }
        } catch (Exception e) {
            System.out.println("BŁĄD ODCZYTU Z PLIKU!");
            System.exit(2);
        }
        try {
            plik.close();
        } catch (IOException e) {
            System.out.println("BŁĄD PRZY ZAMYKANIU PLIKU!");
            System.exit(3);
        }
    }
    public void setData(ObservableList<Table> newData){
       data=newData;
    }

    public ObservableList<Table> getData(){
        return data;
    }

    public void pressButton(ActionEvent event) throws Exception {
        try {
            FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("addClient.fxml"));
            Parent root1 = (Parent) fxmlLoader.load();
            Stage stage = new Stage();
            stage.setTitle("Dodaj klienta");
            stage.setScene(new Scene(root1));
            stage.show();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }


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

        iLp.setCellValueFactory(new PropertyValueFactory<Table, Integer>("rLp"));
        iCity.setCellValueFactory(new PropertyValueFactory<Table, String>("rCity"));
        iDeviceName.setCellValueFactory(new PropertyValueFactory<Table, String>("rDeviceName"));
        iSerialNumber.setCellValueFactory(new PropertyValueFactory<Table, String>("rSerialNumber"));
        iCompanyName.setCellValueFactory(new PropertyValueFactory<Table, String>("rCompanyName"));
        iContact.setCellValueFactory(new PropertyValueFactory<Table, String>("rContact"));
        iSellDate.setCellValueFactory(new PropertyValueFactory<Table, String>("rSellDate"));
        iWarranty.setCellValueFactory(new PropertyValueFactory<Table, Integer>("rWarranty"));
        iNextReview.setCellValueFactory(new PropertyValueFactory<Table, String>("rNextReview"));
        iWarrantyTrue.setCellValueFactory(new PropertyValueFactory<Table, String>("rWarrantyTrue"));


        iLp.setCellFactory(cellFactory2);
        iCity.setCellFactory(cellFactory);
        iDeviceName.setCellFactory(cellFactory);
        iSerialNumber.setCellFactory(cellFactory);
        iCompanyName.setCellFactory(cellFactory);
        iContact.setCellFactory(cellFactory);
        iSellDate.setCellFactory(cellFactory);
        iWarranty.setCellFactory(cellFactory2);
        iNextReview.setCellFactory(cellFactory);
        iWarrantyTrue.setCellFactory(cellFactory);

        tableID.setItems(data);

        //comboboxy
        warrantyLength.setItems(warranty);
        warrantyLength.getSelectionModel().select(0);
        nextReview.setItems(review);
        nextReview.getSelectionModel().select(0);
        warrantyTrue.setItems(warrantyTF);
        warrantyTrue.getSelectionModel().select(0);
    }

}

EditClientController

package controller;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.ComboBox;
import javafx.scene.control.TextField;

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

/**
 * Created by Krzysztof on 2015-01-14.
 */
public class EditClientController implements Initializable {

    @FXML
    ComboBox warrantyLength;
    @FXML
    TextField city;
    public int index;


    //Combo box dla okresu gwarancyjnego
    final ObservableList warranty = FXCollections.observableArrayList("---", 12, 24, 36);

    public void setIndex(int index){
        this.index=index;
    }
    public int getIndex(){
        return index;
    }

    @Override
    public void initialize(URL location, ResourceBundle resources) {
       // city.setText(tablica.get(index).getRCity());
        warrantyLength.setItems(warranty);
        warrantyLength.getSelectionModel().select(0);

    }
}
José Pereda
  • 44,311
  • 7
  • 104
  • 132
Kertt123
  • 63
  • 1
  • 1
  • 7

3 Answers3

6

If you want to specify the controller in the FXML file (so you can't use Deepak's answer) and you want to access the index in the initialize() method (so you can't use José's answer), you can use a controller factory:

FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("editClient.fxml"));
fxmlLoader.setControllerFactory(new Callback<Class<?>, Object>() {
    @Override
    public Object call(Class<?> controllerClass) {
        if (controllerClass == EditClientController.class) {
            EditClientController controller = new EditClientController()
            controller.setIndex(clickIndex);
            return controller ;
        } else {
            try {
                return controllerClass.newInstance();
            } catch (Exception exc) {
                throw new RuntimeException(exc); // just bail
            }
        }
    }
});
Parent root1 = fxmlLoader.load();
James_D
  • 201,275
  • 16
  • 291
  • 322
  • Note that with this approach, you can even make the index a constructor parameter, and get rid of the `setIndex(...)` method if you want. – James_D Jan 15 '15 at 15:11
4

All you need to do is get an instance of your second controller:

EditClientController controller=fxmlLoader.<EditClientController>getController();

and you now will be able to send the required index:

controller.setIndex(clickIndex);

This is all that's required:

    try {
        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("editClient.fxml"));
        Parent root1 = (Parent) fxmlLoader.load();
        EditClientController controller=fxmlLoader.<EditClientController>getController();
        controller.setIndex(clickIndex);
        Stage stage = new Stage();
        stage.setTitle("Edytuj klienta");
        stage.setScene(new Scene(root1));
        stage.show();
    } catch(Exception e) {
        e.printStackTrace();
    }

EDIT

As clickIndex will be sent after the second controller is initialized, this value won't be available on Initialize.

A valid way to solve this is adding a listener to changes:

private IntegerProperty index = new SimpleIntegerProperty(-1);

public void setIndex(int index){
    this.index.set(index);
}
public int getIndex(){
    return index.get();
}

@Override
public void initialize(URL location, ResourceBundle resources) {
    index.addListener((ob,n,n1)->{
        city.setText(tablica.get(n1.intValue()).getRCity());
    });

}
José Pereda
  • 44,311
  • 7
  • 104
  • 132
  • I tryed this way but all times I have cellIndex=0 – Kertt123 Jan 15 '15 at 14:44
  • Do you mean on `EditClientController`? You can't evaluate `index` in its `Initialize` method. You have to call `city.setText(tablica.get(index).getRCity());` after `setIndex()` is called (inside it or adding a listener to changes in index). – José Pereda Jan 15 '15 at 14:52
  • I've edited my answer with a solution for this (in case this was your problem) – José Pereda Jan 15 '15 at 15:04
1

When moving from one controller to another(one view to another), you could initialize the EditClientController with the required parameters

Eg:

FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("editClient.fxml"));
EditClientController ctrl = new EditClientController();
ctrl.setCellIndex(id);
fxmlLoader.setController(ctrl);

If you have specified the controller in the fxml file, the you could use:

editWrapper.getCurrentController().setCellIndex(id);

where editControllerWrapper is a class that loads the new view and has a method getCurrentController that returns an instance of javafx controller.

Eg: public class EditControllerWrapper {

private Parent root;


public EditControllerWrapper () {
    try
    {
        FXMLLoader loader = new FXMLLoader(getClass().getResource("editClient.fxml"),                           
        ...
    } catch (Exception e) {
        ...
    }
}


public <T> T getCurrentController ()  {
    return loader.getController();
}
KayDK
  • 134
  • 10