我在JavaFX应用程序中使用ListView控件。它被设置为MULTIPLE选择模式。我知道作为用户,我可以按住Ctrl键单击一个项目以取消选择它,但这对我的用户来说不够直观。我想要一种方法来第二次点击取消选择它。换句话说,点击一次 - 选择;单击所选项目,它将被取消选中。
我尝试过同时使用ChangeListener和onMouseClicked事件。两者都不是很好。以下是每个代码段。
的ChangeListener:
效果 - 列表中的第一项永远不会被选中。我点击它并保持不被点击。对项目2..n
没有影响listView.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<SpecificAlgorithmData>() {
@Override
public void changed(final ObservableValue observableValue, final SpecificAlgorithmData oldData, final SpecificAlgorithmData newData) {
//if already selected then deselect it
int selectedIndex = listView.getSelectionModel().getSelectedIndex();
System.out.println("selected " + selectedIndex);
System.out.println("all selected" + listView.getSelectionModel().getSelectedIndices());
if (!selecting && !listView.getSelectionModel().getSelectedIndices().contains(selectedIndex)){
Iterator <Integer> iterator = listView.getSelectionModel().getSelectedIndices().iterator();
selecting = true;
listView.getSelectionModel().select(-1);//deselect all
while (iterator.hasNext()){
int index = iterator.next();
if (index!= selectedIndex){
listView.getSelectionModel().select(index);
}
}
selecting = false;
}
}
}
的onClick:
没有效果,因为我不确定如何获取我刚刚点击的索引。由于硬编码,这完全不允许选择第2项。
listView.setOnMouseClicked(new EventHandler<MouseEvent>() {
@Override
public void handle(final MouseEvent mouseEvent) {
int selectedItem = 2; //FIXME: How to I get the index of clicked item?
if (listView.getSelectionModel().isSelected(selectedItem)){
listView.getSelectionModel().clearSelection(selectedItem);
}
}
});
答案 0 :(得分:7)
更改JavaFX中控件的行为非常困难 - API中当前实际上没有钩子进入行为类。
以下似乎可行,方法是在列表中注册一个事件过滤器,直接实现选择行为,并使用该事件。
虽然感觉有点脆弱(例如,如果未来版本决定在鼠标点击时实现默认行为,而不是鼠标按下,或者更好,如果未来版本决定添加鼠标处理的其他功能,该怎么办?事件)。因此,请使用此解决方案,并附上一些“买家提防”通知。
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.control.MultipleSelectionModel;
import javafx.scene.control.SelectionMode;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class DeselectableList extends Application {
@Override
public void start(Stage primaryStage) {
ListView<String> list = new ListView<>();
MultipleSelectionModel<String> selectionModel = list.getSelectionModel();
selectionModel.setSelectionMode(SelectionMode.MULTIPLE);
for (int i=1; i<=20; i++) {
list.getItems().addAll("Item "+i);
}
list.setCellFactory(lv -> {
ListCell<String> cell = new ListCell<>();
cell.textProperty().bind(cell.itemProperty());
cell.addEventFilter(MouseEvent.MOUSE_PRESSED, event -> {
list.requestFocus();
if (! cell.isEmpty()) {
int index = cell.getIndex();
if (selectionModel.getSelectedIndices().contains(index)) {
selectionModel.clearSelection(index);
} else {
selectionModel.select(index);
}
event.consume();
}
});
return cell ;
});
BorderPane root = new BorderPane(list);
Scene scene = new Scene(root, 150, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
显然你比我更了解你的用户,但我可能更喜欢在ListView
上提供一个很好的工具提示,向他们解释如何使用它......