2014-05-13 30 views
5

Używam kontrolki ListView w aplikacji JavaFX. Jest ustawiony na tryb wyboru WIELU. Wiem, że jako użytkownik mogę Ctrl-kliknąć element, aby go odznaczyć, ale to nie jest wystarczająco intuicyjne dla moich użytkowników. Chcę drugi raz kliknąć, aby odznaczyć. Innymi słowy kliknij raz - wybierz; kliknij wybrany element, a zostanie on odznaczony.Odznacz element w javafx ListView na kliknij

Próbowałem używać zarówno zdarzenia ChangeListener, jak i onMouseClicked. Żaden z nich nie działa bardzo dobrze. Poniżej znajdują się fragmenty kodu każdego z nich.

ChangeListener:

efekt - pierwsza pozycja na liście jest NIGDY wybrany. Klikam na niego i pozostaje on niesklasyfikowany. Brak wpływu na przedmioty 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:

żadnego efektu, ponieważ nie jestem pewien, jak zdobyć indeks jednej prostu kliknął. Będąc na sztywno, to po prostu uniemożliwia kiedykolwiek wybierając z punktem 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

Jak użytkownikom wybrać wiele przedmiotów? –

+0

W tej chwili nie wiedzą, że mogą z wciśniętym klawiszem Ctrl, co stanowi problem. Chciałbym, aby mogli wybrać i odznaczyć za pomocą jednego kliknięcia (bez klawisza Ctrl). –

+2

Korzystanie z "Ctrl + kliknięcie" jest powszechnym doświadczeniem użytkownika w wielu aplikacjach Web/Desktop GUI. Możesz uprzejmie przedstawić to swoim użytkownikom. Alternatywnie możesz umieścić pola wyboru w komórkach listy, co może być bardziej intuicyjne. –

Odpowiedz

7

Zmiana zachowania kontroli w JavaFX jest dość trudne - nie ma naprawdę żadnych haczyków obecnie w API do klas zachowań.

Wydaje się, że następujące czynności działają, rejestrując filtr zdarzeń z komórkami na liście, bezpośrednio wprowadzając zachowanie wyboru i pochłaniając zdarzenie.

Czuje się jednak trochę niestabilnie (co, jeśli przyszłe wydanie zdecyduje się zaimplementować domyślne zachowanie po kliknięciu myszą, zamiast na przykład naciśnięciu przycisku myszy, a może lepiej, co jeśli przyszłe wydanie zdecyduje się dodać dodatkową funkcjonalność obsługiwaną przez zdarzenia myszy). Więc użyj tego rozwiązania z załączoną uwagą "kupuj uważnie".

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); 
    } 
} 

Oczywiście wiesz użytkownikom lepiej niż ja, ale może po prostu wolę mieć ładne podpowiedź na ListView wyjaśniając im, jak ją wykorzystać ...

+0

Dziękuję bardzo. Spróbuję tego. Ale jak wskazuje Uluk, mogę po prostu użyć pola listy z polami wyboru. Ostatecznie to zależy od klienta ... –

+0

Tak ... pola wyboru są prawdopodobnie lepszym rozwiązaniem. To jest tak oczywiste, jak możesz zrobić dla swoich użytkowników;). –

+0

Nice! RequestFocus(); zrobił lewę. Idę "do przodu" przez kilka list -> kiedy użytkownik zmienia swój wybór (po raz pierwszy dokonał) i wybiera poprzednią listę (np. Przechodząc do tyłu) zaznaczenie, które pozostaje w stanie nieaktywnym, powinno być nieprawidłowe/rzucone (wybór nieaktywny spowodował, że GUI było niepoprawne). Dzięki! –

Powiązane problemy