是否可以在Javafx中为Listview设置两次单元工厂
问题描述:
我已经在列表视图中设置了一个单元工厂以更改所选单元格的颜色。另一个单元用于拖放操作。两者都不工作时间。 细胞工厂:1是否可以在Javafx中为Listview设置两次单元工厂
listView.setCellFactory(new Callback<ListView<String>, ListCell<String>>()
{
@Override
public ListCell<String> call(ListView<String> param)
{
ListCell<String> listCell = new ListCell<String>()
{
@Override
protected void updateItem(String item, boolean empty)
{
super.updateItem(item, empty);
setText(item);
}
};
Cell factory:2
listView.setCellFactory(list -> {
ListCell<String> cell = new ListCell<String>() {
@Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
setText(empty ? null : item);
}
};
答
setCellFactory
是一组方法,它的行为就像任何其他组的方法:即,它设置ListView
的(唯一)cellFactory
属性的值。就像如果你有一个像
someObject.setIntValue(5);
someObject.setIntValue(42);
代码,你会期望someObject
的intValue
属性为42
,如果调用setCellFactory
两次,电池厂将成为您传递给它的第二个值。
你说你正在试图做的是简单地在单细胞工厂将所有的功能最简单的方法:
listView.setCellFactory(list -> {
ListCell<String> cell = new ListCell<String>() {
@Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
setText(empty ? "" : item);
// modify color here depending on item...
}
};
cell.setOnDragDetected(e -> { /* ... */ });
// other drag handlers...
return cell ;
});
如果你真的想要的东西分离出来,进入不同的工厂实现,你可以用 “装饰” 式的做法:
public class PlainCellFactory implements Callback<ListView<String, ListCell<String>> {
@Override
public ListCell<String> call(ListView<String> list) {
return new ListCell<String>() {
@Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty) ;
setText(empty ? "" : item);
}
};
}
}
加彩:
public class ColorListCellFactory implements Callback<ListView<String>, ListCell<String>> {
private final Callback<ListView<String>, ListCell<String>> originalFactory ;
public ColorListCellFactory(Callback<ListView<String>, ListCell<String>> originalFactory) {
this.originalFactory = originalFactory ;
}
@Override
public ListCell<String> call(ListView<String> list) {
ListCell<String> cell = originalFactory.call(list);
cell.itemProperty().addListener((obs, oldItem, newItem) -> {
// change color depending on newItem (which might be null)...
});
return cell ;
}
}
和拖放:
public class DragAndDropListCellFactory implements Callback<ListView<String>, ListCell<String>> {
private final Callback<ListView<String>, ListCell<String>> originalFactory ;
public DragAndDropListCellFactory(Callback<ListView<String>, ListCell<String>> originalFactory) {
this.originalFactory = originalFactory ;
}
@Override
public ListCell<String> call(ListView<String> list) {
ListCell<String> cell = originalFactory.call(list);
cell.setOnDragDetected(e -> { /* ... */ });
// other drag handlers...
return cell ;
}
}
现在你可以做
PlainCellFactory plainFactory = new PlainCellFactory();
ColorListCellFactory colorFactory = new ColorListCellFactory(plainFactory);
DragAndDropListCellFactory dndFactory = new DragAndDropListCellFactory(colorFactory);
listView.setCellFactory(dndFactory);
答
是否可以设置电池工厂
ListView
两次在JavaFX的?
可以更换单元工厂,但不能让ListView
使用多个工厂来创建单元。
但是,您可以使用通过调用其他对象(策略模式)中的代码来处理项目初始化/替换的单元工厂。这允许您使用组合不同的行为而不需要重新实现单元。
public class MultiBehaviorListCell<S> extends ListCell<S> {
public static interface Behavior<T> {
default void initialize(MultiBehaviorListCell<T> cell) {
}
void updateItem(MultiBehaviorListCell<T> cell, T item, boolean empty);
}
public static <T> Callback<ListView<T>, ListCell<T>> factory(final Behavior<T>... behaviors) {
Objects.requireNonNull(behaviors);
return factory(Arrays.asList(behaviors));
}
private final Iterable<Behavior<S>> behaviors;
private MultiBehaviorListCell(Iterable<Behavior<S>> behaviors) {
this.behaviors = behaviors;
// let behaviors handle initialisation
for (Behavior b : behaviors) {
try {
b.initialize(this);
} catch (RuntimeException ex) {
}
}
}
@Override
protected void updateItem(S item, boolean empty) {
super.updateItem(item, empty);
// let behaviors handle item replacement
for (Behavior<S> b : behaviors) {
try {
b.updateItem(this, item, empty);
} catch (RuntimeException ex) {
}
}
}
public static <T> Callback<ListView<T>, ListCell<T>> factory(final Iterable<Behavior<T>> behaviors) {
Objects.requireNonNull(behaviors);
return l -> new MultiBehaviorListCell<>(behaviors);
}
}
示例使用
@Override
public void start(Stage primaryStage) {
ListView<Integer> listView = new ListView<>();
listView.getItems().addAll(1, 2, 3, 4);
EventHandler<MouseEvent> mouseClicked = evt -> {
MultiBehaviorListCell<Integer> source = (MultiBehaviorListCell<Integer>) evt.getSource();
System.out.println(source.getItem());
};
listView.setCellFactory(MultiBehaviorListCell.factory(
// setting text
(cell, number, empty) -> cell.setText(empty || number == null ? "" : number.toString()),
// changing background/text color
new MultiBehaviorListCell.Behavior<Integer>() {
@Override
public void updateItem(MultiBehaviorListCell<Integer> cell, Integer item, boolean empty) {
}
@Override
public void initialize(MultiBehaviorListCell<Integer> cell) {
cell.setBackground(new Background(new BackgroundFill(Color.YELLOW, CornerRadii.EMPTY, Insets.EMPTY)));
cell.setTextFill(Color.BLACK);
}
},
// registering handler for non-empty cells
(cell, number, empty) -> cell.setOnMouseClicked(empty ? null : mouseClicked)
));
Scene scene = new Scene(listView);
primaryStage.setScene(scene);
primaryStage.show();
}
你可以让两个'CallBack'情况,并参照每次他们中的一个改变'CellFactory'。但问题是为什么你需要两个细胞工厂,而不仅仅是一个具有整体条件的细胞工厂。 – GOXR3PLUS