【问题标题】:Deselect an item on an javafx ListView on click单击时取消选择 javafx ListView 上的项目
【发布时间】:2014-06-30 14:56:33
【问题描述】:

我在 JavaFX 应用程序中使用 ListView 控件。它设置为 MULTIPLE 选择模式。我知道作为用户,我可以按住 Ctrl 键单击一个项目来取消选择它,但这对我的用户来说不够直观。我想要一种方法来再次单击以取消选择它。换句话说,单击一次 - 选择;单击选定的项目,它会变为未选中。

我尝试过同时使用 ChangeListener 和 onMouseClicked 事件。两者都不是很好。下面是每个代码的sn-ps。

变更监听器:

效果 - 列表中的第一项从未被选中。我点击它,它保持未点击状态。对项目 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;
        }
    }
}

点击:

没有效果,因为我不确定如何获取我刚刚单击的索引。由于是硬编码,这根本不允许选择第 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);
        }
    }
});

【问题讨论】:

  • 用户如何选择多个项目?
  • 现在他们不知道他们可以用 Ctrl 键单击这是问题所在。我希望他们能够通过单击(无 Ctrl 键)来选择和取消选择。
  • 使用“Ctrl + 单击”是许多 GUI Web/桌面应用程序的常见用户体验。您可以将其介绍给您的用户。或者,您可以将复选框放在列表单元格上,这可能更直观。
  • 列表框上的复选框,天才。我怎么没想到!!!

标签: java javafx javafx-2


【解决方案1】:

在 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 上有一个很好的工具提示,向他们解释如何使用它...

【讨论】:

  • 非常感谢。我会试试这个。但正如 Uluk 指出的那样,我可能只使用带有复选框的列表框。最终取决于客户...
  • 是的...复选框可能是更好的选择。这对于你的用户来说是显而易见的;)。
  • 不错! requestFocus();成功了。我正在通过几个列表“前进” - >当用户更改他的选择(他第一次做出)并选择前一个列表(如向后导航)时,保持处于非活动状态的选择应该是无效/抛出(不活动的选择使 GUI 不正确)。谢谢!
  • 我在使用这个解决方案时遇到了一些问题,因为在取消选择任何项目后总是选择第一个项目。但是,可以找到解决方法here
猜你喜欢
  • 1970-01-01
  • 2011-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-14
  • 1970-01-01
  • 2016-10-06
  • 1970-01-01
相关资源
最近更新 更多