0

I've a scene where I can create a data, now I want to put it into my TableView "TV_currency".

But this one is into another scene who's already open and I don't want to close and reopen this one.

Can you take a look to it ?

ControllerOptions.java (TV_currency is here) :

public class ControllerOptions implements Initializable{
//VARIABLES    
@FXML private   TableView<Currency> TV_currency;
@FXML private   TableColumn<Currency, String> TC_name;
@FXML private   TableColumn<Currency, Double> TC_value;

private ObservableList<Currency> currencies = FXCollections.observableArrayList();

//FUNCTIONS
@Override
public void initialize(URL location, ResourceBundle rb){
    //initialisation Table Currencies
    for (Currency currency : Datas.getInstance().getCurrencies()) {
        currencies.add(currency);
    }       
    TC_name.setCellValueFactory(new PropertyValueFactory<Currency, String>("name"));
    TC_value.setCellValueFactory(new PropertyValueFactory<Currency, Double>("value"));
    TV_currency.setItems(currencies); //TODO Corriger setItems() de la TableView
}

@FXML void add_currency(MouseEvent event) throws IOException {
    FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("options/currency_add.fxml"));
    Parent root1 = (Parent) fxmlLoader.load();
    Stage stage = new Stage();
    stage.initModality(Modality.APPLICATION_MODAL);
    stage.initStyle(StageStyle.UNDECORATED);
    stage.setTitle("Add new currency");
    stage.setScene(new Scene(root1));  
    stage.setFullScreen(true);
    stage.show();
}

@FXML void open_options(ActionEvent event) throws IOException {
    Group actor = new Group();
    actor.getChildren().add(FXMLLoader.load(getClass().getResource("options.fxml")));
    com.courieux.wheresmymoney.Main.setScene(actor, "Where's My Money");
}
}

ControllerCurrencyAdd.java (where I want to edit TV_currency):

public class ControllerCurrencyAdd {

@FXML private TextField TF_name;
@FXML private TextField TF_value;
@FXML private TextField TF_acronym;

@FXML
void add(ActionEvent event) {
    Currency currency = new Currency(TF_name.getText(), Double.valueOf(TF_value.getText()));
    Datas.getInstance().addCurrency(currency);

    //==> HERE I NEED TO EDIT VARIABLES BELOW <==
    //currencies.setAll(Datas.getInstance().getCurrencies());
    //TV_currency.setItems(currencies);
}
}

Datas.java :

public class Datas {

//SINGLETON PATTERN
private Datas() {}
private static Datas INSTANCE = new Datas();    
public static Datas getInstance(){
    return INSTANCE;
}
//END SINGLETON PATTERN

//VARS
private List<Currency> currencies = new ArrayList<>();

//FUNCTIONS - Add/Edit/Delete
public void addCurrency(Currency currency){
    currencies.add(currency);
}

//FUNCTIONS - getter/setters
public List<Currency> getCurrencies() {
    return currencies;
}
public void setCurrencies(List<Currency> currencies) {
    this.currencies = currencies;
}
}

Currency.java :

public class Currency {

//VARS
private     String      name;
private     double      value;

//FUNCTIONS - constructors
public Currency(String name, double value) {
    setName(name);
    setValue(value);
}

//FUNCTIONS
public boolean equals(Currency currency){
    if(this.name == currency.getName()
            && this.value == currency.getValue()){
        return true;
    } else {
        return false;
    }
}

//FUNCTIONS - getters/setters
public void setName(String name) {
    this.name = name;
}
public String getName() {
    return name;
}
public void setValue(double value) {
    this.value = value;
}
public double getValue() {
    return value;
}
}

Then I want to put new data into the ObservableList "currencies" and set TV_currency with it.

Thanks in advance !

Alexi Courieux
  • 92
  • 2
  • 11
  • You need to create a [Minimal, Complete, and Verifiable example](https://stackoverflow.com/help/mcve). – SedJ601 Aug 02 '17 at 21:42
  • I'll try to make it complete – Alexi Courieux Aug 02 '17 at 21:44
  • Store the data in a separate class (called a "model" in design-pattern terminology) and share an instance of that class with the controllers (this is essentially the idea behind the MVC design pattern). See https://stackoverflow.com/questions/32342864/applying-mvc-with-javafx for an example. Here, if you made your singleton `Datas` return an `ObservableList` you could just do something like `TV_currency.setItems(Datas.getInstance().getCurrencies())` in one controller and then `Datas.getInstance().addCurrency(...)` should update the table automatically. – James_D Aug 02 '17 at 21:53
  • I go look at this, thank you. – Alexi Courieux Aug 02 '17 at 21:55
  • All this look very powerful, I'll take more time to learn MVC pattern(s), thank you ! – Alexi Courieux Aug 02 '17 at 22:13

1 Answers1

1

The simplest change you can make to your code is to let your singleton class hold an ObservableList instead of a List. Then you can use that directly in the table view, and update it directly in other controllers. Since the table view observes its backing list, changes to the observable list will immediately be reflected in the table.

I.e.

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;

public class Datas {

    // SINGLETON PATTERN
    private Datas() {
    }

    private static Datas INSTANCE = new Datas();

    public static Datas getInstance() {
        return INSTANCE;
    }
    // END SINGLETON PATTERN

    // VARS
    private ObservableList<Currency> currencies = FXCollections.observableArrayList();

    // FUNCTIONS - Add/Edit/Delete
    public void addCurrency(Currency currency) {
        currencies.add(currency);
    }

    // FUNCTIONS - getter/setters
    public ObservableList<Currency> getCurrencies() {
        return currencies;
    }

}

and then

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

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Group;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.input.MouseEvent;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

public class ControllerOptions implements Initializable {
    // VARIABLES
    @FXML
    private TableView<Currency> TV_currency;
    @FXML
    private TableColumn<Currency, String> TC_name;
    @FXML
    private TableColumn<Currency, Double> TC_value;

    private ObservableList<Currency> currencies = FXCollections.observableArrayList();

    // FUNCTIONS
    @Override
    public void initialize(URL location, ResourceBundle rb) {
        // initialisation Table Currencies

        TC_name.setCellValueFactory(new PropertyValueFactory<Currency, String>("name"));
        TC_value.setCellValueFactory(new PropertyValueFactory<Currency, Double>("value"));

        // Note how the list from Datas is used directly in the table:
        TV_currency.setItems(Datas.getInstance().getCurrencies()); 
    }

    @FXML
    void add_currency(MouseEvent event) throws IOException {
        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("options/currency_add.fxml"));
        Parent root1 = (Parent) fxmlLoader.load();
        Stage stage = new Stage();
        stage.initModality(Modality.APPLICATION_MODAL);
        stage.initStyle(StageStyle.UNDECORATED);
        stage.setTitle("Add new currency");
        stage.setScene(new Scene(root1));
        stage.setFullScreen(true);
        stage.show();
    }

    @FXML
    void open_options(ActionEvent event) throws IOException {
        Group actor = new Group();
        actor.getChildren().add(FXMLLoader.load(getClass().getResource("options.fxml")));
        Main.setScene(actor, "Where's My Money");
    }
}

and

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.TextField;

public class ControllerCurrencyAdd {

    @FXML
    private TextField TF_name;
    @FXML
    private TextField TF_value;
    @FXML
    private TextField TF_acronym;

    @FXML
    void add(ActionEvent event) {
        Currency currency = new Currency(TF_name.getText(), Double.valueOf(TF_value.getText()));

        // since we update the list used as the table's backing list, the table will automatically update:
        Datas.getInstance().addCurrency(currency);

    }
}

Your Datas class is considered to be a "model" in the MVC (and related) design patterns. Typically making this a singleton can restrict you a bit in terms of modifying the application later (many programmers believe this to be an anti-pattern). You might consider making this a regular class and using dependency-injection techniques to give each controller access to the same instance.

James_D
  • 201,275
  • 16
  • 291
  • 322