javafxduplicatesvboxhboxfiltered

Title: FilteredList in JavaFX returns duplicate results


I am facing an issue with a JavaFX FilteredList. I have a ListView of songs, and I'm using a FilteredList to implement search functionality. When I filter the list by entering a keyword in the search field, the FilteredList returns duplicate results. This duplication issue occurs when I use the FilteredList to display the filtered results in the ListView. Even when the keyword is null, the list still contains duplicate entries. I am using a custom ListCell with three columns (song number, title, artist, and duration) in the ListView. I think the reason is using hbox and vbox.

hbox và vbox:

playList.setCellFactory(new Callback<ListView<Song>, ListCell<Song>>() {
                @Override
                public ListCell<Song> call(ListView<Song> param) {
                    return new ListCell<Song>() {
                        @Override
                        protected void updateItem(Song item, boolean empty) {
                            super.updateItem(item, empty);

                            if (empty || item == null) {
                                setText(null);
                            } else {
                                // Tạo hai nhãn cho mỗi mục
                                Label titleLabel = new Label(item.getTitle());
                                Label artistLabel = new Label(item.getArtist());
                                Label numberLabel = new Label(String.valueOf(item.getsongNumber()));
                                Label DurationLabel = new Label(item.getDuration());
                               
                               
                                
                                // Đặt layout cho nhãn
                                HBox hbox = new HBox();
                                
                                VBox vbox = new VBox(titleLabel,artistLabel);
                                hbox.getChildren().addAll(numberLabel, vbox, DurationLabel);
                                vbox.setMinWidth(275);
                                numberLabel.setMinWidth(36);
                                HBox.setMargin(DurationLabel, new Insets(7, 5, 5, 5));
                                HBox.setMargin(numberLabel, new Insets(7, 0, 5, 5));
                              
                                // Đặt nội dung cho mục
                                setGraphic(hbox);
                                
                            }
                        }
                    };
                }
            });
        // Gán danh sách bài hát trực tiếp cho ListView
            playList.setItems(songs);

filteredList:

 private void filterSongs(String keyword) {
        // Tạo một FilteredList mới từ danh sách bài hát gốc
        newFilteredList = new FilteredList<>(songs);

        System.out.println("Filtering with keyword: " + keyword);
        newFilteredList.setPredicate(song ->
            song.getTitle().toLowerCase().contains(keyword.toLowerCase()) ||
            song.getArtist().toLowerCase().contains(keyword.toLowerCase()));

        System.out.println("Filtered List Size: " + newFilteredList.size());
        for (Song song : newFilteredList) {
            System.out.println(song.getTitle());
        }

        // Đặt FilteredList mới làm nguồn dữ liệu cho ListView
        playList.setItems(newFilteredList);
        playList.refresh(); // Cập nhật hiển thị của ListView
    }

when i search, the filteredList display only true result


Solution

  • Your list cell is incorrectly implemented. Since you set the graphic when the cell is not empty, you need to set it back to null if the cell becomes empty. The implementation should be:

    playList.setCellFactory(new Callback<ListView<Song>, ListCell<Song>>() {
    
        @Override
        public ListCell<Song> call(ListView<Song> param) {
            return new ListCell<Song>() {
                @Override
                protected void updateItem(Song item, boolean empty) {
                    super.updateItem(item, empty);
    
                    if (empty || item == null) {
                        // setText(...) not needed here, since you don't set the text in the else clause:
                        // setText(null);
                        setGraphic(null);
                    } else {
                        // Tạo hai nhãn cho mỗi mục
                        Label titleLabel = new Label(item.getTitle());
                        Label artistLabel = new Label(item.getArtist());
                        Label numberLabel = new Label(String.valueOf(item.getsongNumber()));
                        Label DurationLabel = new Label(item.getDuration());
                       
                       
                        
                        // Đặt layout cho nhãn
                        HBox hbox = new HBox();
                        
                        VBox vbox = new VBox(titleLabel,artistLabel);
                        hbox.getChildren().addAll(numberLabel, vbox, DurationLabel);
                        vbox.setMinWidth(275);
                        numberLabel.setMinWidth(36);
                        HBox.setMargin(DurationLabel, new Insets(7, 5, 5, 5));
                        HBox.setMargin(numberLabel, new Insets(7, 0, 5, 5));
                      
                        // Đặt nội dung cho mục
                        setGraphic(hbox);
                        
                    }
                }
            };
        }
    });