Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typo3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在双ListView选择系统上实现过滤器?_Listview_Exception_Javafx - Fatal编程技术网

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

如何在双ListView选择系统上实现过滤器?,listview,exception,javafx,Listview,Exception,Javafx,我有两个ListView控件,我需要能够在它们之间来回移动项目。移动是通过双击任一列表中的项目来完成的 我还有一个搜索字段,可以从可用的列表中筛选项目。这就是我的麻烦所在 当试图从列表视图的项目中删除项目时,我会收到一个UnsupportedOperationException'。我目前筛选列表的方法似乎是将ListView的列表转换为一个AbstractList`无法编辑 如何在保持基础列表可编辑的同时允许筛选 主类 public class Main extends Application

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

我还有一个搜索字段,可以从
可用的
列表中筛选项目。这就是我的麻烦所在

当试图从列表视图
的项目中删除项目时,我会收到一个
UnsupportedOperationException'。我目前筛选列表的方法似乎是将
ListView
的列表转换为一个
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);

        }
    }
}

控制器类:

<?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);

        }
    }
}
公共类控制器{
@FXML
私有文本字段txtSearch;
@FXML
私有列表视图可用;
@FXML
选择私有列表视图;
私有ObservableList availableList=FXCollections.observableArrayList();
私有ObservableList selectedList=FXCollections.observableArrayList();
@FXML
私有void初始化(){
//可用字符串列表
可用列表addAll(
“一个”,
“两个”,
“三”,
“四”,
“五个”
);
//初始化搜索函数
//将列表包装在过滤列表中(最初显示所有项目)
FilteredList FilteredList=新的FilteredList(availableList.sorted());
//每当过滤器更改时,设置过滤器谓词
txtSearch.textProperty().addListener((可观察、旧值、新值)->{
filteredList.setPredicate(可用项->{
//如果筛选文本为空,则显示所有项目
if(newValue==null | | newValue.isEmpty()){
返回true;
}
//将标记名和搜索标记与筛选文本进行比较
字符串查询=newValue.toLowerCase();
if(availableItem.toLowerCase().contains(查询)){
return true;//查询与可用项匹配
}否则返回availableItem.contains(查询);
});
});
//将筛选后的列表包装在SortedList中
SortedList SortedList=新的SortedList(过滤器列表);
lvAvailable.setItems(FXCollections.observableList(sortedList));
lvAvailable.setPlaceholder(新标签(“无结果”);
//添加双击侦听器以在两个列表之间移动选定的标记
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){
移除项目(lvSelected.getSelectionModel().getSelectedItem());
}
});
}
专用void附加项(字符串项){
//如果标记不在所选列表中。。。
如果(item!=null&!lvSelected.getItems()包含(item)){
//将标记添加到所选列表中
lvSelected.getItems().add(项);
//将其从可用列表中删除
lvAvailable.getItems().remove(项);
}
}
私有void removietem(字符串项){
//如果标记不在所选列表中。。。
if(item!=null&&!lvAvailable.getItems()包含(item)){
//将标记添加到可用列表中
lvAvailable.getItems().add(项);
//将其从所选列表中删除
lvSelected.getItems().remove(项);
}
}
}
首先,您应该使用

lvAvailable.setItems(sortedList);
而不是

lvAvailable.setItems(FXCollections.observableList(sortedList));
SortedList
(和
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);

    }
}

我认为您的MCVE缺少
lvSelected.setItems(selectedList),它是;我在发帖后发现了这一点。现在一切都好了,谢谢!