JavaFX ListView CellFactory禁用项目选择

时间:2016-07-20 23:59:53

标签: java listview javafx

我有一个带有一些值(ListItem)的类,我想显示这些项的列表(ListView<ListItem>)。 ListItem具有value属性,我希望ListView<ListItem>显示为其文本,但除此之外,列表应该看起来和功能正常,特别是关于项目选择。我有以下代码来完成此任务。懒惰中省略了FXML,它只是<ListView />

// Controller for FXML
public class MainController {
    // Wrapper class containing several values
    private class ListItem {
        private String value;

        public ListItem(String value) {
            this.value = value;
        }

        public String getValue() {
            return value;
        }

        ... // Other useful stuff
    }

    @FXML private ListView<ListItem> list;

    @FXML
    public void initialize() {
        // Set list to display using the given CellFactory
        list.setCellFactory((list) -> {
            return new ListCell<ListItem>() {
                @Override
                protected void updateItem(ListItem item, boolean empty) {
                    if (empty) return;

                    // Display item's value property
                    setText(item.getValue());
                }
            };
        });

        // Add test data
        list.getItems().add(new ListItem("test"));
        list.getItems().add(new ListItem("test2"));

        // Print when selection changes
        list.getSelectionModel().selectedItemProperty().addListener((evt) -> {
            System.out.println("Selection changed!");
        });
    }
}

这会在ListItem的每个项目中使用value属性正确显示ListView。但是,它会中断选择,并且System.out.println(...)不会执行(该项也会在GUI中突出显示)。我发现删除list.setCellFactory(...)声明是罪魁祸首,但让我陷入困境。

list.setCellFactory(...)存在时,该项目使用正确的文本,但无法被选中。如果缺少list.setCellFactory(...),则该项目使用错误的文本,但可以被选中。为了正确显示文本选择项目,我还需要做些什么特别的事情吗?

我已经完成了先决条件谷歌搜索,但我找不到其他任何有这个特殊问题的人。非常感谢任何帮助。

1 个答案:

答案 0 :(得分:7)

您需要添加

super.updateItem(item, empty);

作为updateItem(...)的第一行。此调用必须始终出现在已覆盖的Cell.updateItem(...)方法中(其他updateXXX方法也是如此,例如updateIndex(...))。

此外,您还应确保updateItem(...)方法正确处理所有情况,包括单元格为空的情况:

protected void updateItem(ListItem item, boolean empty) {
    super.updateItem(item, empty);
    if (empty) {
        setText(null);
    } else {
        // Display item's value property
        setText(item.getValue());
    }
}