如何在双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)代码>,它是;我在发帖后发现了这一点。现在一切都好了,谢谢!