我有两个ListView
控件,我需要能够在它们之间来回移动项目。通过双击任一列表中的项目来完成移动。
我还有一个搜索字段,可以过滤Available
列表中的项目。这就是我的麻烦所在。
我得到一个UnsupportedOperationException' when trying to remove an item from the
ListView 's items. My current method of filtering the list seems to convert the
ListView '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);
}
}
}
答案 0 :(得分:0)
首先,你应该使用
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);
}
}