具有通用 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
的类型。此后所有通用变量都使用此类型参数,因此编译器可以知道它全部匹配。
我有两种 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
的类型。此后所有通用变量都使用此类型参数,因此编译器可以知道它全部匹配。