2014-05-13 73 views
5

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

我试过使用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); 
     } 
    } 
}); 
+1

如何在用户选择多个项目? –

+0

现在他们不知道他们可以用Ctrl键点击这是问题所在。我希望他们能够通过点击(无Ctrl键)来选择和取消选择。 –

+2

使用“Ctrl + Click”是许多GUI Web /桌面应用程序的常见用户体验。您可以将其介绍给您的用户。或者,您可以将复选框放在列表单元格中,这可能更直观。 –

回答

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

+0

非常感谢。我会试试这个。但是,正如乌鲁克指出的,我可能只是使用带有复选框的列表框。最终它取决于客户... –

+0

是的...复选框可能是一个更好的方式去。这是明显的,你可以为你的用户;)。 –

+0

不错! requestFocus();取得了诀窍。我通过几个列表“向前” - >当用户更改他的选择(他第一次创建)并选择以前的列表(如向后导航)时,保持非活动状态的选择应该无效/抛出不活动的选择使GUI不正确)。谢谢! –

相关问题