JavaFX ListView滚动时未达标单元格错误着色问题求助
Fix for Incorrect Cell Coloring in JavaFX ListView Due to Cell Reuse
Yep, this classic issue boils down to JavaFX's cell reuse mechanism—when you scroll the ListView, cells that were colored for "done" items get repurposed for new entries, but your code doesn't reset the background when the new item doesn't meet the condition. Let's fix this step by step.
First, Fix the updateItem Method
Your current code has two key issues:
- You're calling
super.updateItem(item, empty)after your custom logic—this should be the first line in the method, since it handles critical cell state resets. - You don't reset the background for items that don't end with "done", so reused cells keep their old color.
Here's the corrected version of your ChangeColor cell class:
groupCheckListView.setCellFactory(new Callback<ListView<String>, ListCell<String>>() { @Override public ListCell<String> call(ListView<String> param) { return new ChangeColor(); } }); class ChangeColor extends ListCell<String> { @Override protected void updateItem(String item, boolean empty) { // Always call super first to handle cell state reset super.updateItem(item, empty); if (empty || item == null) { setText(null); setGraphic(null); setBackground(null); // Reset background for empty cells } else { setText(item); if (item.toLowerCase().endsWith("done")) { // Set light green background for done items setBackground(new Background(new BackgroundFill( Paint.valueOf("#58FF2D"), CornerRadii.EMPTY, Insets.EMPTY ))); } else { // Reset background to default for non-done items setBackground(null); // Alternatively, match your CSS default: // setBackground(new Background(new BackgroundFill( // Paint.valueOf("white"), // CornerRadii.EMPTY, // Insets.EMPTY // ))); } } } }
A More Elegant Approach: Use CSS Classes
Instead of hardcoding colors in Java, using CSS classes is cleaner and more maintainable. Here's how to implement it:
- Update your CSS file to add a custom class for done cells:
.list-cell:empty { -fx-background-color: white; } .done-cell { -fx-background-color: #58FF2D; }
- Modify your cell class to add/remove the CSS class based on the condition:
class ChangeColor extends ListCell<String> { @Override protected void updateItem(String item, boolean empty) { super.updateItem(item, empty); if (empty || item == null) { setText(null); setGraphic(null); getStyleClass().remove("done-cell"); // Clean up class for empty cells } else { setText(item); if (item.toLowerCase().endsWith("done")) { if (!getStyleClass().contains("done-cell")) { getStyleClass().add("done-cell"); } } else { getStyleClass().remove("done-cell"); } } } }
Additional Tips
- If your list data updates periodically (every X time) or on button clicks, use an
ObservableListfor your ListView items—this will automatically trigger cell updates. If you're using a regular List, callgroupCheckListView.refresh()after updating the data to force all cells to re-render. - Always remember: cell reuse means every state (background, text, graphics) needs to be explicitly set or reset in
updateItem—never assume a cell starts with a clean state.
内容的提问来源于stack exchange,提问作者Nicolas Caro
相关产品推荐
相关产品推荐

