是否可以在Javafx中为Listview设置两次单元工厂

是否可以在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); 

         } 
        }; 
+0

你可以让两个'CallBack'情况,并参照每次他们中的一个改变'CellFactory'。但问题是为什么你需要两个细胞工厂,而不仅仅是一个具有整体条件的细胞工厂。 – GOXR3PLUS

setCellFactory是一组方法,它的行为就像任何其他组的方法:即,它设置ListView的(唯一)cellFactory属性的值。就像如果你有一个像

someObject.setIntValue(5); 
someObject.setIntValue(42); 

代码,你会期望someObjectintValue属性为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(); 
}