在下面的测试中,所选列表项应与绿色标记一起显示。它适用于最初选择的项目。但是,当选择另一个项目时,似乎没有调用#updateItem(),这似乎是标记未正确更新的原因。
public class ComboBoxCellFactoryTest extends Application
{
public static void main(String[] args)
{
Application.launch(args);
}
@Override
public void start(Stage stage)
{
Parent content = createContent();
Scene scene = new Scene(content, 400, 300);
stage.setScene(scene);
stage.show();
}
public Parent createContent()
{
FlowPane content = new FlowPane(10, 10);
ComboBox<String> combo = new ComboBox<String>();
combo.setItems(FXCollections.observableArrayList("Item 1", "Item 2", "Item 3", "Item 4"));
combo.getSelectionModel().selectLast();
combo.setCellFactory(new Callback<ListView<String>, ListCell<String>>()
{
@Override
public ListCell<String> call(ListView<String> p)
{
return new ListCell<String>()
{
private final Rectangle rectangle;
{
rectangle = new Rectangle(10, 10);
}
@Override
protected void updateItem(String item, boolean empty)
{
super.updateItem(item, empty);
if (empty || item == null)
{
setText(null);
setGraphic(null);
}
else
{
boolean selected = combo.getValue().equals(item);
rectangle.setFill(selected ? Color.GREENYELLOW : Color.RED);
setGraphic(rectangle);
setText(item);
}
}
};
}
});
content.getChildren().add(combo);
return content;
}
}
答案 0 :(得分:3)
对我来说看起来像个错误。解决方法(未经过正式测试,只需快速检查!)可能是使用单元格的选定属性注册侦听器并手动强制执行updateItem,如:
{
rectangle = new Rectangle(10, 10);
selectedProperty().addListener((c, ov, nv) -> {
updateItem(getItem(), getItem() == null);
});
}
<小时/> 的更新强>
实际上,它似乎比简单的bug更糟糕:
updateItem(...)
没有指定任何内容。它只包含诸如之类的模糊,可以重写以允许完全自定义单元格 看到最后(和最差)子弹,运行下面的示例(这是包含在一个简单的应用程序中的激励示例),选择一个项目(请注意文本颜色未按预期更改为白色)和滚动项目-by-item:在第二页的某处,有一条不可见的线(又名:文字颜色为白色)。发生的原因是因为在updateItem与selectedIndex无关时选择了isSelected(显示在列表下方的标签中)
public class CellUpdateItemAndSelected extends Application {
public static void main(String[] args) {
Application.launch(args);
}
@Override
public void start(Stage stage) {
Parent content = createContent();
Scene scene = new Scene(content, 400, 300);
stage.setScene(scene);
stage.show();
}
public Parent createContent() {
Pane content = new VBox(10);
ListView<Number> numberList = new ListView<>(createNumberData(20));
// this is the motivating example from cell's api doc
numberList.setCellFactory(cf -> {
ListCell<Number> cell = new ListCell<Number>() {
@Override
protected void updateItem(Number item, boolean empty) {
super.updateItem(item, empty);
setText(item == null ? "" : item.toString());
if (item != null) {
double value = item.doubleValue();
setTextFill(isSelected() ? Color.WHITE
: value == 0 ? Color.BLACK
: value < 0 ? Color.RED : Color.GREEN);
if (isSelected()) {
LOG.info("selected index/item: " + getIndex() + " / " + item);
}
}
}
};
return cell;
});
Label selectedLabel = new Label();
selectedLabel.textProperty().bind(numberList.getSelectionModel().selectedIndexProperty().asString());
content.getChildren().addAll(numberList, selectedLabel);
return content;
}
protected ObservableList<Number> createNumberData(int count) {
ObservableList<Number> data = FXCollections.observableArrayList();
for (int i = -3; i < count; i++) {
data.add(i);
}
return data;
}
@SuppressWarnings("unused")
private static final Logger LOG = Logger
.getLogger(CellUpdateItemAndSelected.class.getName());
}
更新2
工作从错误开始:补丁内核现在调用updateSelected中的updateItem(...),如
public void updateSelected(boolean selected) {
if (selected && isEmpty()) return;
setSelected(selected);
// fix for JDK-8145588
updateItem(getItem(), isEmpty());
}
必须对所有其他单元状态属性执行相同操作...