JavaFX TableView с ChangeListener для множественного выбора

Я хочу прослушивать изменения выбора в табличном представлении в JavaFX 8. Если я добавляю ChangeListener к selectedItemProperty (или selectedIndexProperty) MultipleSelectionModel, он не срабатывает в следующем случае: несколько строк уже выбраны, и теперь я выбираю новый одна линия. Если эта строка является последней выбранной ранее строкой, она не реагирует. Это связано с тем, что selectedItemProperty содержит только один элемент, а не список всех выбранных. Но, к сожалению, нет свойства selectedItems, что странно, потому что метод getSelectedItems() существует. Я не знаю, куда добавить слушателя, чтобы он работал в любом случае.

Вот пример кода:

import java.util.stream.Collectors;
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.ListView;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

public class MultipleSelectionTest extends Application
{
    private ListView<Integer> list = new ListView<>();
    private TableView<String> table = new TableView<>();
    private TableColumn<String, String> column1 = new TableColumn<>("Numbers");

    @Override
    public void start(Stage primaryStage) throws Exception
    {
        HBox box = new HBox(list, table);
        primaryStage.setScene(new Scene(box, 300, 500));
        initializeTable();
        initializeList();
        primaryStage.show();
    }

    private void initializeTable()
    {
        table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
        table.getColumns().add(column1);
        column1.setCellValueFactory(s -> new SimpleStringProperty(s.getValue()));
        table.setItems(FXCollections.observableArrayList("One", "Two", "Three", "Four", "Five", "Six", "Seven"));
    }

    private void initializeList()
    {
        table.getSelectionModel().selectedItemProperty().addListener((property, oldValue, newValue) ->
        {
            ObservableList<Integer> convertedItems = FXCollections.observableList(
                table.getSelectionModel().getSelectedItems()
                .stream()
                .map(this::convertNumber)
                .collect(Collectors.toList()));

            list.setItems(convertedItems);
        });
    }

    private int convertNumber(String expression)
    {
        switch (expression)
        {
            case "One": return 1;
            case "Two": return 2;
            case "Three": return 3;
            case "Four": return 4;
            case "Five": return 5;
            case "Six": return 6;
            case "Seven": return 7;
            default: throw new IllegalArgumentException();
        }
    }

    public static void main(String[] args)
    {
        launch();
    }
}

Обратите внимание, что ListView в этом примере предназначен только для визуальных целей.


person Arceus    schedule 01.01.2016    source источник


Ответы (2)


Вам не нужен selectedItemsProperty - getSelectedItems возвращает ObservableList, к которому вы можете добавить слушателя.

Наличие свойства для этого означало бы, что объект списка изменился, но на самом деле происходит то, что список остается тем же самым object, но его содержимое меняется.

person Itai    schedule 01.01.2016

Вот более полное решение, которое было найдено благодаря указателю ответа SillyFly.

В моем примере предполагается, что таблица настроена для работы с произвольным классом Person, который определяет имя, фамилию и адрес электронной почты.

//Set the table to multi selection mode
table.getSelectionModel().setSelectionMode( SelectionMode.MULTIPLE);

//Regiseter the listener on the ObervableList<Person>
table.getSelectionModel().getSelectedItems().addListener(multiSelection);


  /**A listener for list selections, multiple selections in the TableView**/
     ListChangeListener< Person> multiSelection = new ListChangeListener<Person>(){
        @Override
        public void onChanged(  ListChangeListener.Change<? extends Person> changed){
            for( Person p : changed.getList())
                System.out.println(p);
        } 
     };
person Andrew S    schedule 06.04.2016