2012-07-10 30 views
8
TableColumn<Event,Date> releaseTime = new TableColumn<>("Release Time"); 
    releaseTime.setCellValueFactory(
       new PropertyValueFactory<Event,Date>("releaseTime") 
      ); 

Jak zmienić format releaseTime? W tej chwili wywołuje prosty toString na obiekcie Date.Formatowanie komórek tabeli JavaFX

Odpowiedz

5

Musiałem to zrobić niedawno -

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; 
     } 
    }); 

Jednak - to dużo łatwiejsze w Javie 8 stosując Lamba wyrażeń:

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

Pośpiesz się z tym Java 8 Wydanie wyroczni!

+1

Działa to dobrze dla początkowego zapełniania tabeli ... jeśli właściwość daty w modelu zmienia się później niż SimpleStringProperty nie wysyła powiadomienia, a tabela nie jest aktualizowana. – Adam

7

Jeśli chcesz zachować możliwości sortowania w TableColumn, żadne z powyższych rozwiązań nie jest poprawne: jeśli konwertujesz swoją datę na ciąg i pokazuje to w ten sposób w swoim TableView; tabela posortuje ją jako taką (tak niepoprawnie).

Rozwiązanie, które znalazłem, podklasy klasy Date w celu nadpisania metody toString(). Istnieje jednak zastrzeżenie: TableView używa java.sql.Date zamiast java.util.Date; więc musisz podklasować ten pierwszy.

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); 
    } 
} 

Tabela wywoła tę metodę w celu wydrukowania daty.

Oczywiście, trzeba zmienić też datę klasę w deklaracji TableColumn do nowej podklasy:

@FXML 
TableColumn<MyObject, CustomDate> myDateColumn; 

samo po podłączeniu swój atrybut obiektu do kolumny tabeli:

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

I wreszcie, dla poruszenia jasności ten sposób można zadeklarować getter w swojej klasie obiektu:

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

Zajęło mi trochę czasu, aby dowiedzieć się, ze względu na to, że używa java.sql.Date za kulisami; więc mam nadzieję, że to zaoszczędzi innym ludziom trochę czasu!

4

Aktualizacja FX8 Java:

(nie jestem pewien, że jest to dobre miejsce dla tej odpowiedzi, ale pojawia się problem w JavaFX8 i pewne rzeczy się zmieniły, podobnie jak pakiet java.time)

Niektóre różnice z poprzednimi odpowiedziami: Zachowuję typ daty na kolumnie, więc muszę użyć zarówno cellValueFactory, jak i cellFactory. I Utwórz ogólną metodę wielokrotnego użytku do generowania cellFactory dla wszystkich kolumn daty. Używam daty java 8 dla pakietu java.time! Ale metoda może być łatwo ponownie zaimplementowana dla 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)); 
     } 
     } 
    }; 
    }; 
} 

Zalety są takie, że:

  • Kolumna jest wpisany z „java8 Date”, aby uniknąć problemu sortowania evoqued przez @Jordan
  • Metoda „getDateCell” jest nazwą rodzajową i może być używany jako funkcja util dla wszystkich typów czasu Java8 (lokalne strefy itp.)
4

Polecam używanie generycznych Java do tworzenia wielokrotnego użytku formatera kolumn, który ma dowolny java.text.Format. Ten zmniejszają ilości kodu boilerplate ...

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))); 
       } 
      } 
     }; 
    } 
} 

Przykłady użycia

birthday.setCellFactory(new ColumnFormatter<Person, Date>(new SimpleDateFormat("dd MMM YYYY"))); 
amplitude.setCellFactory(new ColumnFormatter<Levels, Double>(new DecimalFormat("0.0dB"))); 
2

To co zrobiłem i działało idealnie.

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"))); 
      } 
     } 
    }; 
}); 
1

Uniwersalny rozwiązaniem mogłoby być takie proste:

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);   
} 

I jego wykorzystanie próbki:

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)); 
0

można łatwo Właściwości rur różnego typu i umieścić formatowania lub konwertera pomiędzy.

//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; 
       }); 
Powiązane problemy