Search code examples
listviewjavafxcontrollerreload

JAVAFX LISTVIEW REFRESH TAB


I'm stuck in school projet.

I have javafx project, with a Controller A and Controller B. The A controller is associated with Tab A, and B conrtoller with Tab B.

In both controller, I have a listview listing the same object (@FXML Listview moviesList for example).

In Tab A, I can remove a movie from the listview. No problem, the object is deleted from the listview.

But problem, when I switch on the Tab B, the object is still in the Listview.

And I don't know how to refresh this listview after deleting the object.

Main.java

public class Main extends Application {

private Stage primaryStage;
private TabPane rootLayout;
private Tab tabMovie = new Tab("Movies");
private Tab tabRoom = new Tab("Rooms");


@Override
    public void start(Stage primaryStage) throws Exception {
        this.primaryStage = primaryStage;
        this.primaryStage.setTitle("Javaravi Admin");
        primaryStage.setResizable(false);

        loadScreen();

        showMovies();

        showRoomsAndShows();


    }


public void loadScreen() {
        try {
            FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("menu.fxml"));
            rootLayout = fxmlLoader.load();

            // Show the scene containing the root layout.
            Scene scene = new Scene(rootLayout);
            scene.getStylesheets().add(Main.class.getResource("style.css").toExternalForm());
            rootLayout.getTabs().addAll(tabMovie, tabRoom, tabParam);
            primaryStage.setScene(scene);
            primaryStage.show();

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


public void showMovies() {
        try {
            FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("movie.fxml"));
            AnchorPane filmView = fxmlLoader.load();

            // Set person overview into the center of root layout.

            tabMovie.setContent(filmView);

            // Give the controller access to the main app.
            MovieController controller = fxmlLoader.getController();


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



public void showRoomsAndShows() {
        try {
            FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("system.fxml"));
            AnchorPane room = fxmlLoader.load();

            // Set person overview into the c enter of root layout.
            tabRoom.setContent(room);

            // Give the controller access to the main app.
            SystemController systemController = fxmlLoader.getController();


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

MovieController.java

public class MovieController {

    @FXML
    private ListView<Film> moviesListView;

    private Database db = Database.getInstance();
    private ModelFactory mf = ModelFactory.getInstance();

    public MovieController() {
    }

    private void showAllMovies() {

        List<Film> moviesList = new ArrayList<>();
        List<Model> modelsList = mf.getAllModels("Film");
        for (int i=0; i<modelsList.size(); i++) {
            moviesList.add((Film) modelsList.get(i));
        }
        ObservableList<Film> myObservableList = FXCollections.observableList(moviesList);
        setMoviesItems(myObservableList);
    }

    private void setMoviesItems(ObservableList<Film> item) {

        moviesListView.setItems(item);
    }

@FXML
    private void initialize() {

        showAllMovies();
    }

    @FXML
    private void deleteShow() {

        Film selectedFilm = moviesListView.getSelectionModel().getSelectedItem();

            System.out.println("Validation suppression");
            selectedFilm.removeFromDb();
            showAllMovies();
            moviesListView.requestFocus();
            moviesListView.getSelectionModel().select(0);
            getSelectedMovie();      

    }

Show.java

public class SystemController {

@FXML
private ListView<Film> selectedMovieResa;

@FXML
    private void initialize() {

        // initialize lists
        showAllLanguages();
        showAllShows();
        showAllMovies();
        showAllRooms();
    }

// set movies list
    private void showAllMovies() {

        // same process as the first one (line 158, set room list)
        List<Film> moviesList = new ArrayList<>();
        List<Model> modelsList = mf.getAllModels("Film");
        for (int i=0; i<modelsList.size(); i++) {
            moviesList.add((Film) modelsList.get(i));
        }
        ObservableList<Film> myObservableList = FXCollections.observableList(moviesList);
        setMoviesItems(myObservableList);
    }

    public void setMoviesItems(ObservableList<Film> item) {

        selectedMovieResa.setItems(item);
        movieFromShow.setItems(item);
        filterMovie.setItems(item);
    }

Tks !


Solution

  • The problem is each of your ListViews contains a different ObservableList with the data. So removing from one list will not remove from the other. The best solution is to let both list views share a single data list.

    Have your ModelFactory class create a (single) ObservableList<Model> and return it via a getMovies() method. Something like

    public class ModelFactory {
    
        private ObservableList<Film> filmList = null ;
    
        // existing code...
    
        public ObservableList<Film> getMovies() {
            if (filmList == null) {
                List<Film> films = new ArrayList<>();
                List<Model> models = getAllModels("Film");
                for (Model m : models) {
                    films.add((Film)m);
                }
                filmList = FXCollections.observableList(films);
            }
            return filmList ;
        }
    
        // ...
    }
    

    Then you just have a single list that can be shared by the various views:

    public class SystemController {
    
        // ...
    
        public void showAllMovies() {
            setMoviesItems(mf.getMovies());
        }
    
        // ...
    }
    

    and

    public class MoviesController {
    
        // ...
    
        public void showAllMovies() {
            setMoviesItems(mf.getMovies());
        }
    
        // ...
    
        @FXML
        private void deleteShow() {
            Film selectedFilm = moviesListView.getSelectionModel().getSelectedItem();
            selectedFilm.removeFromDb();
            // since list is shared, this will be observed in all views...
            moviesListView.getItems().remove(selectedFilm); 
        }
    
        // ...
    }
    

    A similar, simpler (but complete) example is at https://github.com/james-d/SharedListView