Вопрос по format, render, cell, javafx-2 – Форматирование ячеек таблицы JavaFX

8
    TableColumn<Event,Date> releaseTime  = new TableColumn<>("Release Time");
    releaseTime.setCellValueFactory(
                new PropertyValueFactory<Event,Date>("releaseTime")
            );

Как я могу изменить формат releaseTime? На данный момент он вызывает простую строку toString для объекта Date.

Ваш Ответ

8   ответов
0

ми форматтер или конвертер.

    //from my model
    ObjectProperty<Date> valutaProperty;

    //from my view
    TableColumn<Posting, String> valutaColumn;

    valutaColumn.setCellValueFactory(
            cellData -> {
                  SimpleStringProperty property = new SimpleStringProperty();
                  property.bindBidirectional(cellData.getValue().valutaProperty,  new SimpleDateFormat("dd.MM.yyyy", Locale.GERMAN));
                  return property;
               });
2

tbColDataMovt.setCellFactory((TableColumn<Auditoria, Timestamp> column) -> {
    return new TableCell<Auditoria, Timestamp>() {
        @Override
        protected void updateItem(Timestamp item, boolean empty) {
            super.updateItem(item, empty);
            if (item == null || empty) {
                setText(null);
            } else {
                setText(item.toLocalDateTime().format(DateTimeFormatter.ofPattern("dd/MM/yyyy")));
            }
        }
    };
});
2

import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.util.Callback;

public interface AbstractConvertCellFactory<E, T> extends Callback<TableColumn<E, T>, TableCell<E, T>> {

    @Override
    default TableCell<E, T> call(TableColumn<E, T> param) {
        return new TableCell<E, T>() {
            @Override
            protected void updateItem(T item, boolean empty) {
                super.updateItem(item, empty);
                if (item == null || empty) {
                    setText(null);
                } else {
                    setText(convert(item));
                }
            }
        };
    }

    String convert(T value);        
}

И его пример использования:

TableColumn<Person, Timestamp> dateCol = new TableColumn<>("employment date");
dateCol.setCellValueFactory(new PropertyValueFactory<>("emploumentDateTime"));    
dateCol.setCellFactory((AbstractConvertCellFactory<Person, Timestamp>) value -> new SimpleDateFormat("dd-MM-yyyy").format(value));
9

ни одно из приведенных выше решений не является действительным: если вы преобразуете свою Date в String и покажите ее таким образом в TableView; таблица будет сортировать как таковую (так неправильно).

Решением, которое я нашел, было создание подкласса класса Date для переопределения метода toString (). Здесь есть предостережение: TableView использует java.sql.Date вместо java.util.Date; так что вам нужно подкласс первого.

import java.text.SimpleDateFormat;

public class CustomDate extends java.sql.Date {

    public CustomDate(long date) {
        super(date);
    }

    @Override
    public String toString() {
        return new SimpleDateFormat("dd/MM/yyyy").format(this);
    }
}

Таблица будет вызывать этот метод для печати даты.

Конечно, вам также необходимо изменить свой класс Date в объявлении TableColumn на новый подкласс:

@FXML
TableColumn<MyObject, CustomDate> myDateColumn;

То же самое, когда вы присоединяете атрибут объекта к столбцу таблицы:

myDateColumn.setCellValueFactory(new PropertyValueFactory< MyObject, CustomDate>("myDateAttr"));

И, наконец, для ясности, вот как вы объявляете метод получения в своем классе объектов:

public CustomDate getMyDateAttr() {
    return new CustomDate(myDateAttr.getTime()); //myDateAttr is a java.util.Date           
}

Мне потребовалось некоторое время, чтобы понять это из-за того, что он использует java.sql.Date за кулисами; так что, надеюсь, это сэкономит время другим людям!

7

орно используемого средства форматирования столбцов, которое принимает любыеjava.text.Format, Это сокращает количество стандартного кода ...

private class ColumnFormatter<S, T> implements Callback<TableColumn<S, T>, TableCell<S, T>> {
    private Format format;

    public ColumnFormatter(Format format) {
        super();
        this.format = format;
    }
    @Override
    public TableCell<S, T> call(TableColumn<S, T> arg0) {
        return new TableCell<S, T>() {
            @Override
            protected void updateItem(T item, boolean empty) {
                super.updateItem(item, empty);
                if (item == null || empty) {
                    setGraphic(null);
                } else {
                    setGraphic(new Label(format.format(item)));
                }
            }
        };
    }
}

Примеры использования

birthday.setCellFactory(new ColumnFormatter<Person, Date>(new SimpleDateFormat("dd MMM YYYY")));
amplitude.setCellFactory(new ColumnFormatter<Levels, Double>(new DecimalFormat("0.0dB")));
но какое свойство это использовать? в вашем образце нет имени свойства.
6

dateAddedColumn.setCellValueFactory(
   new Callback<TableColumn.CellDataFeatures<Film, String>, ObservableValue<String>>() {
      @Override
      public ObservableValue<String> call(TableColumn.CellDataFeatures<Film, String> film) {
         SimpleStringProperty property = new SimpleStringProperty();
         DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
         property.setValue(dateFormat.format(film.getValue().getCreatedDate()));
         return property;
      }
   });

Однако - этоlot проще в Java 8, используя выражения Lamba:

dateAddedColumn.setCellValueFactory(
   film -> {
      SimpleStringProperty property = new SimpleStringProperty();
      DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
      property.setValue(dateFormat.format(film.getValue().getCreatedDate()));
      return property;
   });

Спешите с этим оракулом выпуска Java 8!

Это прекрасно работает для первоначального заполнения таблицы ... если свойство даты в модели изменяется позже, чем SimpleStringProperty, не отправляет уведомление, и таблица не обновляется.
4


https://stackoverflow.com/a/10149050/682495
https://stackoverflow.com/a/10700642/682495
Хотя вторая ссылка оListCellта же логика полностью применима кTableCellс тоже.

Постскриптум Тем не менее, если вам нужен пример кода, пожалуйста, приложите здесь.

4

(Я не уверен, что это подходящее место для такого ответа, но у меня проблема в JavaFX8, и некоторые вещи изменились, например, в пакете java.time)

Некоторые отличия от предыдущих ответов: Я сохраняю тип даты в столбце, поэтому мне нужно использовать и cellValueFactory, и cellFactory. Я делаю универсальный метод многократного использования для генерации cellFactory для всех столбцов даты. Я использую дату java 8 для пакета java.time! Но метод может быть легко переопределён для java.util.date.

 @FXML
 private TableColumn<MyBeanUi, ZonedDateTime> dateColumn;

@FXML
public void initialize () {
  // The normal binding to column 
  dateColumn.setCellValueFactory(cellData -> cellData.getValue().getCreationDate());

  //.. All the table initialisation and then
  DateTimeFormatter format = DateTimeFormatter .ofLocalizedDate(FormatStyle.SHORT);
  dateColumn.setCellFactory (getDateCell(format));

}

public static <ROW,T extends Temporal> Callback<TableColumn<ROW, T>, TableCell<ROW, T>> getDateCell (DateTimeFormatter format) {
  return column -> {
    return new TableCell<ROW, T> () {
      @Override
      protected void updateItem (T item, boolean empty) {
        super.updateItem (item, empty);
        if (item == null || empty) {
          setText (null);
        }
        else {
          setText (format.format (item));
        }
      }
    };
  };
}

Преимущества в том, что:

The column is typed with a "java8 Date" to avoid the sort problem evoqued by @Jordan The method "getDateCell" is generic and can be used as an util function for all Java8 Time types (Local Zoned etc.)

Похожие вопросы