具有通用 class 的 JavaFX 自定义 ComboBox

JavaFX custom ComboBox with generic class

我有两种 classes 扩展 class X

public class A extends X

public class B extends X

在我的 JavaFX 应用程序中,需要有一个组合框。此组合框是使用 classes A 或 B 构建的,并使用 class 各自的 toString() 方法进行填充。减少代码重复。

我正在尝试修改我当前生成组合框的方法,这样它将允许类型为 A 或 B 的 ObservableList。

protected ComboBox<? extends X> getComboBox(ObservableList<? extends X> list){
    ComboBox<? extends X> comboBox = new ComboBox<>();
    comboBox.setItems(list);
    comboBox.setCellFactory(new Callback<ListView<? extends X>, ListCell<? extends X>>() {
        @Override
        public ListCell<Controller> call(ListView<Controller> param) {

            return new ListCell<? extends X>(){
                @Override
                public void updateItem(Class<? extends X> content, boolean empty){
                    super.updateItem(content, empty);
                    if(!empty) {
                        setText(content.toString());
                    } else {
                        setText(null);
                    }
                }
            };
        }
    });
    return comboBox;
}

因为两个 classes 都有一个超级class,是否有可能实现这样的事情(并且可能,但不是本质上,return 它是原始的 class类型)

@SillyFly - 我使用 Reflections 依赖项检索列表。它 return 是特定类型(即 A)的所有 class

public ObservableList<A> getAList() {
    Reflections reflection = new Reflections("com.classes.aClasses");
    ObservableList<A> classesList = FXCollections.observableArrayList();
    for (Class<? extends A> thisClass : reflection.getSubTypesOf(A.class)) {
        try {
            classesList.add(thisClass.newInstance());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    return classesList;
}

我很确定默认的 ListCell 实现使用 toString 来渲染项目,因此设置单元工厂可能是多余的。

至于你的问题 - 问题是 ComboBox<T> 需要其 items 属性 为 ObservableList<T>。由于您使用 generic wildcard 作为类型参数,编译器无法知道这是否是同一类型。

你需要做的是给方法一个 generic type parameter:

protected <T extends X> ComboBox<T> getComboBox(ObservableList<T> list){
    ComboBox<T> comboBox = new ComboBox<>();
    comboBox.setItems(list);
    // Setting a cell factory is probably redundant if you're only using toString...
    return comboBox;
} 

请注意,我们定义了一个类型参数 T 并强制它成为扩展 X 的类型。此后所有通用变量都使用此类型参数,因此编译器可以知道它全部匹配。