如果使用不同的列选择多行,则 SelectedItems 为空

SelectedItems empty if multiple rows selected using different columns

我在 SelectionMode.MULTIPLE 中有一个 TableView。使用 ListChangeListener 我能够捕获多行的 selection(通过按 Shift)。

但是,我的解决方案只有在没有列的区域中 select 在同一列 中编辑时才有效。带有 4 个示例的 GIF 插图:

  1. 确定: 在状态列
  2. 中使用 Shift 选择 3 项
  3. 确定: 在 Idx 列中使用 Shift 选择 4 个项目
  4. 确定: 使用 Shift 选择 4 个项目,从 State 列开始到没有列的区域
  5. 错误: 尝试使用 Shift select 4 个项目,从状态列开始到数据项列

问题似乎是 SelectedItems-list 在最后一个例子中显然是空的。非常感谢您就此问题提供的帮助。

这是我的方法:

ObservableList<DataRowModel> dataRows = FXCollections.observableArrayList();
dataRows.addAll(dataSetModel.getRows());
tableDataRow.setItems(dataRows);
tableDataRowStateColumn.setCellValueFactory(f -> f.getValue().getState());

tableDataRow.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
tableDataRow.getSelectionModel().getSelectedItems()
.addListener((ListChangeListener.Change<? extends DataRowModel> c) -> {
    while (c.next()) {
        c.getRemoved().stream().forEach(remitem -> remitem.setSelected(false));
        c.getAddedSubList().stream().forEach(additem -> additem.setSelected(true));
        System.out.println(c.getList()); //Empty [] when selected using different columns
    }
});

只是为了更好地理解我的代码:setSelected(...) 在我的 DataRowModel 上设置了一个 BooleanProperty,它绑定到 State-Column。

没有上下文,使用这个 selected-属性 的原因似乎很愚蠢。但是,还有其他各种代码片段,其中 ChangeListeners 绑定到 selected-属性.

SSCCE 准备 运行:

import javafx.application.Application;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.stage.Stage;

public class TableViewSample extends Application {

    private TableView<DataRowModel> tableDataRow = new TableView<DataRowModel>();
    private TableColumn<DataRowModel, String> tableDataRowNameColumn = new TableColumn<>("Data Item");
    private TableColumn<DataRowModel, String> tableDataRowStateColumn = new TableColumn<>("State");

    private final ObservableList<DataRowModel> dataRows =
        FXCollections.observableArrayList(
            new DataRowModel("Concinna",  false),
            new DataRowModel("Concinna",  false),
            new DataRowModel("Concinna",  false),
            new DataRowModel("Concinna",  false),
            new DataRowModel("Concinna",  false)
        );

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

    @Override
    public void start(Stage stage) {
        Scene scene = new Scene(new Group());
        stage.setTitle("Table View Sample");
        stage.setWidth(500);
        stage.setHeight(500);

        tableDataRow.setItems(dataRows);
        tableDataRowNameColumn.setCellValueFactory(f -> f.getValue().getName());
        tableDataRowStateColumn.setCellValueFactory(f -> f.getValue().getState());

        tableDataRow.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
        tableDataRow.getSelectionModel().getSelectedItems()
          .addListener((ListChangeListener.Change<? extends DataRowModel> c) -> {
            while (c.next()) {
                c.getRemoved().stream().forEach(remitem -> remitem.setSelected(false));    
                c.getAddedSubList().stream().forEach(additem -> additem.setSelected(true));                
            }
        });

        tableDataRow.getColumns().addAll(tableDataRowNameColumn, tableDataRowStateColumn);

        ((Group) scene.getRoot()).getChildren().addAll(tableDataRow);

        stage.setScene(scene);
        stage.show();
    }

    public static class DataRowModel {
        private StringProperty name = new SimpleStringProperty(this, "name", "");
        private BooleanProperty selected = new SimpleBooleanProperty(this, "selected", true);
        private StringProperty state = new SimpleStringProperty(this, "state", "");

        public DataRowModel(String name, boolean selected) {
            this.name.setValue(name);
            this.selected.setValue(selected);

            this.selected.addListener((observable, oldVal, newVal) -> {
                getState(); // Refresh State value
            });
        }

        public StringProperty getName() {
            return name;
        }
        public BooleanProperty isSelected() {
            return selected;
        }
        public void setSelected(boolean selected) {
            if (this.selected.getValue() != selected)
                this.selected.setValue(selected);
        }

        public StringProperty getState() {
            String stateStr = "";
            if (selected.getValue())
                stateStr += "Selected";
            state.setValue(stateStr);
            return state;
        }
    }
}

我能够通过编辑 Oracle 的 Person 表视图示例生成它。

这是一个错误,已提交为 https://bugs.openjdk.java.net/browse/JDK-8096787,并已在预计于 2015 年 8 月发布的 8u60 版本中修复。