TableView items not refreshing, but are correctly added, after adding them from a different controller

116 Views Asked by At

First I want to say that I already checked various similar solutions to this problem here, but the code design of the other users that posted this question is so different than mine that I don't understand how to fix the same problem using the solutions posted.

That said, I'm using javafx with gluon scene builder to create my first app. I'll post the code below. This (https://i.stack.imgur.com/SJvrX.png) is how the app looks so far. The New button opens this window (https://i.stack.imgur.com/281S8.png).

I have a main class called WeightApp:

    package application;
    
    import javafx.application.Application;
    import javafx.fxml.FXMLLoader;
    import javafx.scene.Parent;
    import javafx.scene.Scene;
    import javafx.stage.Stage;
    
    public class WeightApp extends Application {
    
        @Override
        public void start(Stage primaryStage) throws Exception{
            Parent root = FXMLLoader.load(getClass().getResource("foodTab.fxml"));
            Scene main = new Scene(root);
            primaryStage.setScene(main);
            primaryStage.setTitle("App");
            primaryStage.setMinWidth(root.minWidth(-1));
            primaryStage.setMinHeight(root.minHeight(-1));
            primaryStage.show();
        }
    
        public static void main(String[] args) {
            launch(WeightApp.class);
        }
    }

A FoodTabController class which loads what's shown in the first picture without the window created by pressing New:

    package application;

    import application.domain.Aliment;
    import javafx.collections.FXCollections;
    import javafx.collections.ObservableList;
    import javafx.fxml.FXML;
    import javafx.fxml.FXMLLoader;
    import javafx.scene.Parent;
    import javafx.scene.Scene;
    import javafx.scene.control.*;
    import javafx.scene.control.cell.PropertyValueFactory;
    import javafx.scene.layout.AnchorPane;
    import javafx.stage.Stage;
    import java.io.*;
    import java.util.Objects;

    public class FoodTabController {

        @FXML
        protected AnchorPane app, foodTab, foodButtonBar;

        @FXML
        protected TabPane mainWindow;

        @FXML
        protected Tab summaryTabLabel, foodTabLabel;

        @FXML
        protected Label alimentsLabel;

        @FXML
        protected Button deleteButton, refreshButton, newButton, newMealWindow;

        @FXML
        protected TableView<Aliment> alimentsTableView;

        @FXML
        protected TableColumn<Aliment, String> alimentsNameCol;

        @FXML
        protected TableColumn<Aliment, Double> alimentsKcalCol, alimentsFatCol, alimentsCarbsCol, alimentsProteinCol, alimentsFiberCol;

        protected ObservableList<Aliment> aliments = FXCollections.observableArrayList();

        public void initialize() {
            alimentsNameCol.setCellValueFactory(new PropertyValueFactory<>("name"));
            alimentsKcalCol.setCellValueFactory(new PropertyValueFactory<>("calories"));
            alimentsFatCol.setCellValueFactory(new PropertyValueFactory<>("fat"));
            alimentsCarbsCol.setCellValueFactory(new PropertyValueFactory<>("carbohydrate"));
            alimentsProteinCol.setCellValueFactory(new PropertyValueFactory<>("protein"));
            alimentsFiberCol.setCellValueFactory(new PropertyValueFactory<>("fiber"));

            loadAliments();

            alimentsTableView.setItems(aliments);

        }

        // Aliments //

        public void newAlimentWindow() throws IOException {
            Parent newAlimentWindow = FXMLLoader.load(Objects.requireNonNull(getClass().getResource("newAlimentWindow.fxml")));
            Stage stage = new Stage();
            stage.setScene(new Scene(newAlimentWindow));
            stage.show();
        }

        public void updateTableView() {
            aliments.clear();
            loadAliments();
        }

        public ObservableList<Aliment> alimentObservableList() {
            return aliments;
        }

        public void deleteAliment() {
            aliments.remove(alimentsTableView.getSelectionModel().getSelectedItem());
            saveAliments();
        }

        public void saveAliments() {
            String COMMA_DELIMITER = ",";
            String NEW_LINE_SEPARATOR = "\n";
            String FILE_HEADER = "aliment,calories,fat,carbs,protein,fiber";

            FileWriter fw = null;

            try {
                fw = new FileWriter("aliments.csv");

                fw.append(FILE_HEADER);
                fw.append(NEW_LINE_SEPARATOR);

                for (Aliment aliment : aliments) {
                    fw.append(String.valueOf(aliment.getName()));
                    fw.append(COMMA_DELIMITER);
                    fw.append(String.valueOf(aliment.getCalories()));
                    fw.append(COMMA_DELIMITER);
                    fw.append(String.valueOf(aliment.getFat()));
                    fw.append(COMMA_DELIMITER);
                    fw.append(String.valueOf(aliment.getCarbohydrate()));
                    fw.append(COMMA_DELIMITER);
                    fw.append(String.valueOf(aliment.getProtein()));
                    fw.append(COMMA_DELIMITER);
                    fw.append(String.valueOf(aliment.getFiber()));
                    fw.append(NEW_LINE_SEPARATOR);
                }
            } catch (Exception e) {
                System.out.println("Error writing to file");
                e.printStackTrace();
            } finally {
                try {
                    assert fw != null;
                    fw.flush();
                    fw.close();
                } catch (IOException e) {
                    System.out.println("Error while flushing/closing FileWriter.");
                    e.printStackTrace();
                }
            }
        }

        public void loadAliments()  {
            String COMMA_DELIMITER = ",";
            int ALIMENT_NAME = 0;
            int ALIMENT_CALORIES = 1;
            int ALIMENT_FAT = 2;
            int ALIMENT_CARBS = 3;
            int ALIMENT_PROTEIN = 4;
            int ALIMENT_FIBER = 5;

            BufferedReader fileReader = null;

            try {
                fileReader = new BufferedReader(new FileReader("aliments.csv"));
                fileReader.readLine();
                String line = "";

                while ((line = fileReader.readLine()) != null) {
                    String[] tokens = line.split(COMMA_DELIMITER);
                    aliments.add(new Aliment(String.valueOf(tokens[ALIMENT_NAME]), Double.parseDouble(tokens[ALIMENT_CALORIES]), Double.parseDouble(tokens[ALIMENT_FAT]), Double.parseDouble(tokens[ALIMENT_CARBS]), Double.parseDouble(tokens[ALIMENT_PROTEIN]), Double.parseDouble(tokens[ALIMENT_FIBER])));

                }
            } catch (Exception e) {
                System.out.println("Error reading aliments from CSV file");
                e.printStackTrace();
            } finally {
                try {
                    assert fileReader != null;
                    fileReader.close();
                } catch (IOException e) {
                    System.out.println("Error while trying to close FileReader");
                    e.printStackTrace();
                }
            }

        }
        // Aliments //
    }

Finally, I have the newAlimentWindowController class that is the window the New button opens:

    package application;

    import application.domain.Aliment;
    import javafx.fxml.FXML;
    import javafx.scene.control.Button;
    import javafx.scene.control.TextField;
    import javafx.scene.layout.Pane;

    public class newAlimentWindowController extends FoodTabController {

        @FXML
        protected Pane newAlimentPane;

        @FXML
        protected TextField newAlimentSetName, newAlimentSetCal, newAlimentSetFat, newAlimentSetCarbs, newAlimentSetProtein, newAlimentSetFiber;

        @FXML
        protected Button addButton;

        public void initialize() {
            loadAliments();
        }

        public void addAliment() {
            aliments.add(new Aliment(newAlimentSetName.getText(), Double.parseDouble(newAlimentSetCal.getText()), Double.parseDouble(newAlimentSetFat.getText()), Double.parseDouble(newAlimentSetCarbs.getText()), Double.parseDouble(newAlimentSetProtein.getText()), Double.parseDouble(newAlimentSetFiber.getText())));
            saveAliments();
            updateTableView();
        }
    }

Also, the Aliment object:

    package application.domain;
    
    import java.util.Objects;
    
    public class Aliment {
    
        private String name;
        private double weight;
        private double calories, fat, carbohydrate, protein, fiber;
    
        public Aliment(String name, double weight, double calories, double fat, double carbohydrate, double protein, double fiber) {
           this(name, calories, fat, carbohydrate, protein, fiber);
           this.weight = weight;
        }
    
        public Aliment(String name, double calories, double fat, double carbohydrate, double protein, double fiber) {
            this.name = name;
            this.weight = 100;
            this.calories = calories;
            this.fat = fat;
            this.carbohydrate = carbohydrate;
            this.protein = protein;
            this.fiber = fiber;
        }

Everything works fine, except after I type in the textfields in the New window and I press the Add button, the updateTableView method inside the addAliment method doesn't trigger (the Aliment item is added correctly, the observable list just doesn't refresh on the Add button press). However, the updateTableView method does work if I trigger it from inside the FoodTabController class that I linked to the Refresh button.

I don't understand what's happening: I can interact with the aliments observable list in FoodTabController from newAlimentWindowController since aliments.add works and at the same time, the saveAliments method also works, but updateTableView method, that is in the same method as saveAliments and aliments.add, does not work. I'm very confused.

I feel like I'm missing something basic about java programming and as such I'd like to learn what's going on. Any help will be appreciated, thank you very much!

0

There are 0 best solutions below