JavaFX:点击时如何设置多个ListView项的文本与样式
问题解答
一、为什么去掉else语句后其他列表项会消失?
JavaFX的ListView采用单元格复用机制:列表中的cell不会为每个item单独创建,当列表滚动或者数据更新时,已有的cell会被重新用来显示新的item。
你的updateItem方法里,如果没有else分支,当cell被复用来显示未被点击过的item时,因为不满足item.matches(mySelection)的条件,就不会执行setText操作,导致cell保留之前的内容(可能是空或者之前点击项的文本),看起来就像其他列表项“消失”了。else分支的作用就是在item不匹配当前选中项时,将cell的文本重置为item本身,保证所有未被修改的项都能正常显示。
二、如何让所有点击过的项都显示修改效果?
当前代码的问题在于:每次执行performAction时,都会重新设置cellFactory,而且cell里只判断item是否等于最后一次点击的mySelection,之前点击的项不会被识别到。解决步骤如下:
- 只初始化一次cellFactory:把cellFactory的设置移到初始化方法(比如
initialize())里,不要每次点击都重新设置。 - 检查item是否在已点击列表中:在
updateItem里,判断当前item是否存在于Context.getInstance().getItemsClicked()中,而不是只和单次的mySelection比较。 - 点击后刷新列表:每次添加新的点击项后,调用
guiList.refresh()触发所有cell重新渲染。
修改后的代码示例:
@FXML private ListView<String> guiList; // 初始化时设置一次cellFactory public void initialize() { guiList.setCellFactory(param -> new ListCell<String>() { @Override protected void updateItem(String item, boolean empty) { super.updateItem(item, empty); if (empty || item == null) { setText(null); setStyle(""); setFont(Font.font(Font.getDefault().getFamily(), Font.getDefault().getSize())); return; } List<String> clickedItems = Context.getInstance().getItemsClicked(); // 判断当前item是否被点击过 if (clickedItems != null && clickedItems.contains(item)) { // 若需要记录每个item对应的action,可将selectedList改为Map<String, Actions>类型 setText(item + " [已处理]"); setFont(Font.font(Font.getDefault().getFamily(), FontWeight.BOLD, Font.getDefault().getSize())); setStyle("-fx-text-fill: green;"); } else { setText(item); setFont(Font.font(Font.getDefault().getFamily(), Font.getDefault().getSize())); setStyle(""); } } }); } void performAction(Actions action) { try { String mySelection = Context.getInstance().getSelected(); List<String> selectedList = Context.getInstance().getItemsClicked(); if (selectedList == null) { selectedList = new ArrayList<>(); } // 避免重复添加同一个item if (!selectedList.contains(mySelection)) { selectedList.add(mySelection); Context.getInstance().setItemsClicked(selectedList); // 刷新列表,让所有cell重新渲染 guiList.refresh(); } } catch (Exception e) { e.printStackTrace(); // 建议不要空捕获异常,至少打印异常信息便于排查 } }
补充说明
如果需要为每个点击的item记录对应的Actions类型,建议把Context里的itemsClicked改成Map<String, Actions>,这样在updateItem时可以获取到每个item对应的action,显示更准确的文本(比如item + " [" + action + "]")。
内容的提问来源于stack exchange,提问作者zephirus
相关产品推荐
相关产品推荐

