JavaFX:如何批量切换选中TableRow的样式?
问题:TableView多选行切换颜色失效,仅修改最后一行
我给TableView的每行都配置了ContextMenu,点击菜单项“Contrassegna riga come analizzata”时,希望切换所有选中行的颜色(已着色则移除),但当前代码只修改最后选中的一行,代码如下:
tableView.setRowFactory( new Callback<TableView, TableRow>() { @Override public TableRow call(TableView tableView0) { final TableRow row = new TableRow<>(); final ContextMenu rowMenu = new ContextMenu(); final PseudoClass checkedPC = PseudoClass.getPseudoClass("checked"); MenuItem doneRiga = new MenuItem("Contrassegna riga come analizzata"); doneRiga.setOnAction(j -> { if (!row.getPseudoClassStates().contains(checkedPC)) row.pseudoClassStateChanged(checkedPC, true); else row.pseudoClassStateChanged(checkedPC, false); }); MenuItem doneArticolo = new MenuItem("Contrassegna articolo come analizzato"); rowMenu.getItems().addAll(doneRiga, doneArticolo); return row; } });
解决建议
问题根源
当前代码仅操作了创建ContextMenu时的单一行对象(row变量),没有遍历TableView的所有选中行,所以只会修改右键点击的那一行(或最后选中行)。
修正方案
在菜单项的点击事件中,通过TableView的选择模型获取所有选中行,逐个切换伪类状态:
tableView.setRowFactory( new Callback<TableView, TableRow>() { @Override public TableRow call(TableView tableView0) { final TableRow row = new TableRow<>(); final ContextMenu rowMenu = new ContextMenu(); final PseudoClass checkedPC = PseudoClass.getPseudoClass("checked"); MenuItem doneRiga = new MenuItem("Contrassegna riga come analizzata"); doneRiga.setOnAction(j -> { // 获取所有选中的行 ObservableList<TableRow> selectedRows = tableView0.getSelectionModel().getSelectedItems() .stream() .map(item -> tableView0.getRow(item)) .filter(Objects::nonNull) .collect(Collectors.toCollection(FXCollections::observableArrayList)); // 逐个切换伪类状态 for (TableRow selectedRow : selectedRows) { boolean isChecked = selectedRow.getPseudoClassStates().contains(checkedPC); selectedRow.pseudoClassStateChanged(checkedPC, !isChecked); } }); MenuItem doneArticolo = new MenuItem("Contrassegna articolo come analizzato"); rowMenu.getItems().addAll(doneRiga, doneArticolo); return row; } });
更优实践(推荐)
将选中状态绑定到数据模型的属性上,更符合JavaFX的MVVM设计思想,避免直接操作UI组件:
- 在你的数据实体类中添加一个布尔属性:
private final BooleanProperty checked = new SimpleBooleanProperty(false); public boolean isChecked() { return checked.get(); } public BooleanProperty checkedProperty() { return checked; } public void setChecked(boolean checked) { this.checked.set(checked); } - 在rowFactory中绑定伪类状态到数据属性:
row.pseudoClassStateChanged(checkedPC, row.getItem() != null && row.getItem().isChecked()); // 监听属性变化自动更新UI row.itemProperty().addListener((obs, oldItem, newItem) -> { if (oldItem != null) { oldItem.checkedProperty().removeListener(checkedListener); } if (newItem != null) { newItem.checkedProperty().addListener(checkedListener); row.pseudoClassStateChanged(checkedPC, newItem.isChecked()); } else { row.pseudoClassStateChanged(checkedPC, false); } }); final ChangeListener<Boolean> checkedListener = (obs, oldVal, newVal) -> row.pseudoClassStateChanged(checkedPC, newVal); - 菜单项点击事件中直接更新数据模型:
doneRiga.setOnAction(j -> { tableView0.getSelectionModel().getSelectedItems().forEach(item -> { item.setChecked(!item.isChecked()); }); });
内容的提问来源于stack exchange,提问作者Andrea Lombardi
相关产品推荐
相关产品推荐

