2016-02-04 4 views
0

Я работаю с JavaFX с нескольких недель и после долгого времени, чтобы иметь дело с tableView & TreeTableView, я прихожу к вам, чтобы лучше понять Cell Factory.Пользовательские ячейки для каждой ячейки JavaFX

Мой первый вопрос касается глобального подхода CellFactory в JavaFX.

Обычно фабрика предназначена для производства различных объектов с различным поведением. Но, в JavaFX CellFactory, похоже, создает один и тот же тип ячеек для всей колонки ...

Какой подход относится к шаблону Factory Design?

Если я хочу изменить поведение Ячейки в зависимости от содержимого (значения) ячейки, я не могу (как я видел до сих пор).

Итак, мой первый вопрос (Барабанная дробь ...):

Как я создавать собственные фабрики ячеек для каждой ячейки в TableColumn в зависимости от содержания ячейки?

ответ

1

Какой подход относится к шаблону заводского проектирования?

Да, так оно и есть. Вся цель шаблона фабрики позволяет классу, использующему его (TableView), создавать экземпляры классов, придерживающихся определенного контракта (TableCell), но скрывая от него конкретную реализацию.

Рабочий процесс показан на диаграмме на этой странице: http://www.oodesign.com/factory-pattern.html

Просто заменить Client с TableView и Product с TableCell ...

Это позволяет создавать классы многократного использования для cellFactory и cellValueFactory без необходимости менять что-либо расширение TableView/TableColumn. (Просто взгляните на javafx.scene.control.cell package, у большинства (или даже всех) ячеек есть статический метод создания фабрики для своего типа, которые работают независимо от TableView элементов и могут использоваться вместе, например, с помощью PropertyValueFactory).

Как создать пользовательскую фабрику ячеек для каждой ячейки таблицы TableColumn в зависимости от содержимого ячейки?

У вас нет. Вы пишете ячейку таблицы, которая решает ее компоновку в зависимости от содержимого, переданного путем изменения свойств и свойств объекта text и graphic. когда элемент изменяется (item владелец дома или updateItem метод).

Пример для клеток, воспроизводящих классов, показывая экземпляр, созданный с помощью конструктора по умолчанию:

column1.setCellFactory(v -> new TableCell<Class<? extends Node>, Class<? extends Node>>() { 

    @Override 
    protected void updateItem(Class<? extends Node> item, boolean empty) { 
     super.updateItem(item, empty); 
     if (empty) { 
      setGraphic(null); 
     } else { 
      try { 
       setGraphic(item.getConstructor().newInstance()); 
      } catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | InvocationTargetException ex) { 
       setGraphic(null); 
      } 
     } 
    } 

}); 

Это предполагает, что вы можете решить, макет, учитывая значение элемента.

Если вы не можете спроектировать чистый код с этим подходом, рассмотреть вопрос об объединении его с шаблоном стратегии, то есть пусть ваши детали решают макет TableCell:

@FunctionalInterface 
public interface TableCellLayouter { 
    void layoutCell(TableCell<?, ?> cell); 
} 
// the content could be more complex of course 
TableView<TableCellLayouter> tv = new TableView<>(FXCollections.observableArrayList(
     cell -> { 
      cell.setText(null); 
      cell.setGraphic(new Rectangle(100, 100)); 
     }, 
     cell -> { 
      cell.setGraphic(null); 
      cell.setText("Hello world!"); 
     }, 
     cell -> { 
      cell.setGraphic(new Circle(20)); 
      cell.setText("circle"); 
     })); 

TableColumn<TableCellLayouter, TableCellLayouter> column1 = new TableColumn<>("a"); 
column1.setCellValueFactory(c -> Bindings.createObjectBinding(() -> c.getValue())); 

column1.setCellFactory(v -> new TableCell<TableCellLayouter, TableCellLayouter>() { 

    @Override 
    protected void updateItem(TableCellLayouter item, boolean empty) { 
     super.updateItem(item, empty); 
     if (empty) { 
      setGraphic(null); 
      setText(null); 
     } else { 
      item.layoutCell(this); 
     } 
    } 

}); 
+0

OK, если бы я правильно поняли, изменение фабрики не является решением, но применить изменение к методу Cell on update() - единственный способ. В моем случае я отображаю только текст в ячейке, так что поведение редактирования должно быть разным, в зависимости от типа объекта в ячейке oi должны генерировать другое текстовое поле с различным поведением, когда я редактирую другую ячейку, и я должен определить ее на startEdit() не так ли? – Doremus

+1

@Doremus: Да, ячейки могут быть использованы повторно для эффективности, но вы решаете на заводе, какой класс ячеек вы используете или каким-то образом модифицируете ячейку. Метод 'updateItem' - это не единственный способ сделать это. Регистрация слушателя в свойство ['item' ячейки] (https://docs.oracle.com/javase/8/javafx/api/javafx/scene/control/Cell.html#itemProperty) также может работать и может быть полезным , если вам нужно отменить изменения в зависимости от элемента, ранее показанного в ячейке. – fabian

+0

tks для вашего ответа @fabian! Последний вопрос, этот слушатель по свойству item, где его определить? На моей фабрике ячеек? в классе, где я инициализирую свое табличное представление? – Doremus

Смежные вопросы