代码之家  ›  专栏  ›  技术社区  ›  Zephyr

如何在双ListView选择系统上实现过滤器?

  •  0
  • Zephyr  · 技术社区  · 6 年前

    我有两个 ListView 控件,我需要能够在这些控件之间来回移动项目。移动是通过双击任一列表中的项目来完成的。

    我还有一个搜索字段,可以从 Available 列表这就是我的麻烦所在。

    我得到一个 UnsupportedOperationException' when trying to remove an item from the 列表视图 's items. My current method of filtering the list seems to convert the 列表视图 's list to an AbstractList`无法编辑。

    如何在保持基础列表可编辑的同时允许过滤?

    主要类别

    public class Main extends Application {
    
        @Override
        public void start(Stage primaryStage) throws Exception{
            Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
            primaryStage.setTitle("Hello World");
            primaryStage.setScene(new Scene(root, 300, 275));
            primaryStage.show();
        }
    
    
        public static void main(String[] args) {
            launch(args);
        }
    }
    

    FXML布局:

    <?xml version="1.0" encoding="UTF-8"?>
    
    <?import javafx.geometry.Insets?>
    <?import javafx.scene.control.*?>
    <?import javafx.scene.layout.*?>
    <VBox fx:id="vboxMain" alignment="center" spacing="10" xmlns="http://javafx.com/javafx/9.0.1"
          xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
    
        <padding>
            <Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
        </padding>
        <children>
            <HBox spacing="10.0">
                <children>
                    <VBox fx:id="vboxAvailableSearchTags" spacing="5.0">
                        <children>
                            <Label style="-fx-font-weight: bold;" text="Available"/>
                            <TextField fx:id="txtSearch" prefWidth="100.0"/>
                            <ListView fx:id="lvAvailable" prefHeight="200.0" prefWidth="100.0"/>
                        </children>
                    </VBox>
                    <VBox prefHeight="200.0" prefWidth="100.0" spacing="5.0">
                        <children>
                            <Label style="-fx-font-weight: bold;" text="Seleted"/>
                            <ListView fx:id="lvSelected" prefHeight="200.0" prefWidth="100.0" VBox.vgrow="ALWAYS"/>
                        </children>
                    </VBox>
                </children>
                <padding>
                    <Insets top="10.0"/>
                </padding>
            </HBox>
        </children>
    
    </VBox>
    

    控制器类别:

    public class Controller {
    
        @FXML
        private TextField txtSearch;
        @FXML
        private ListView<String> lvAvailable;
        @FXML
        private ListView<String> lvSelected;
    
        private ObservableList<String> availableList = FXCollections.observableArrayList();
        private ObservableList<String> selectedList = FXCollections.observableArrayList();
    
        @FXML
        private void initialize() {
            // List of available strings
            availableList.addAll(
                    "One",
                    "Two",
                    "Three",
                    "Four",
                    "Five"
            );
    
            // Initialize the search function
            // Wrap the list in a filtered list (initially showing all items)
            FilteredList<String> filteredList = new FilteredList<>(availableList.sorted());
    
            // Set the filter predicate whenever the filter changes
            txtSearch.textProperty().addListener((observable, oldValue, newValue) -> {
                filteredList.setPredicate(availableItem -> {
                    // If filter text is empty, show all items
                    if (newValue == null || newValue.isEmpty()) {
                        return true;
                    }
    
                    // Compare the tag name and search tags with the filter text
                    String query = newValue.toLowerCase();
    
                    if (availableItem.toLowerCase().contains(query)) {
                        return true;    // Query matches the available item
                    } else return availableItem.contains(query);
                });
    
            });
    
            // Wrap the filtered list in a SortedList
            SortedList<String> sortedList = new SortedList<>(filteredList);
    
            lvAvailable.setItems(FXCollections.observableList(sortedList));
            lvAvailable.setPlaceholder(new Label("No results"));
    
            // Add the double-click listeners to move selected tags between the two lists
            lvAvailable.setOnMouseClicked(mouseEvent -> {
                if (mouseEvent.getButton().equals(MouseButton.PRIMARY) &&
                        mouseEvent.getClickCount() == 2) {
                    addItem(lvAvailable.getSelectionModel().getSelectedItem());
                }
            });
            lvSelected.setOnMouseClicked(mouseEvent -> {
                if (mouseEvent.getButton().equals(MouseButton.PRIMARY) &&
                        mouseEvent.getClickCount() == 2) {
                    removeItem(lvSelected.getSelectionModel().getSelectedItem());
                }
            });
        }
    
        private void addItem(String item) {
    
            // If the tag is not already in the Selected list...
            if (item != null && !lvSelected.getItems().contains(item)) {
    
                // Add the tag to the Selected list
                lvSelected.getItems().add(item);
    
                // Remove it from the available list
                lvAvailable.getItems().remove(item);
    
            }
        }
    
        private void removeItem(String item) {
    
            // If the tag is not already in the Selected list...
            if (item != null && !lvAvailable.getItems().contains(item)) {
    
                // Add the tag to the Available list
                lvAvailable.getItems().add(item);
    
                // Remove it from the Selected list
                lvSelected.getItems().remove(item);
    
            }
        }
    }
    
    1 回复  |  直到 6 年前
        1
  •  0
  •   James_D    6 年前

    首先,您应该使用

    lvAvailable.setItems(sortedList);
    

    而不是

    lvAvailable.setItems(FXCollections.observableList(sortedList));
    

    A. SortedList (和a FilteredList )都是 不可修改的 (因为允许修改将违反对其进行排序和/或筛选的合同)。您应该修改基础列表:

    private void addItem(String item) {
    
        // If the tag is not already in the Selected list...
        if (item != null && !selectedList.contains(item)) {
    
            // Add the tag to the Selected list
            selectedList.add(item);
    
            // Remove it from the available list
            availableList.remove(item);
    
        }
    }
    
    private void removeItem(String item) {
    
        // If the tag is not already in the Selected list...
        if (item != null && !selectedList.contains(item)) {
    
            // Add the tag to the Available list
            availableList.add(item);
    
            // Remove it from the Selected list
            selectedList.remove(item);
    
        }
    }