可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
TableColumn releaseTime = new TableColumn("Release Time"); releaseTime.setCellValueFactory( new PropertyValueFactory("releaseTime") );
How can I change the format of releaseTime? At the moment it calls a simple toString on the Date object.
回答1:
You can accomplish that through Cell Factories. See
https://stackoverflow.com/a/10149050/682495
https://stackoverflow.com/a/10700642/682495
Although the 2nd link is about ListCell
, the same logic is totally applicable to TableCell
s too.
P.S. Still if you need some sample code, kindly will attach here.
回答2:
If you want to preserve the sorting capabilities of your TableColumn, none of the solutions above is valid: if you convert your Date to a String and show it that way in your TableView; the table will sort it as such (so incorrectly).
The solution I found was subclassing the Date class in order to override the toString() method. There is a caveat here though: the TableView uses java.sql.Date instead of java.util.Date; so you need to subclass the former.
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); } }
The table will call that method in order to print the date.
Of course, you need to change too your Date class in the TableColumn declaration to the new subclass:
@FXML TableColumn myDateColumn;
Same thing when you attach your object attribute to the column of your table:
myDateColumn.setCellValueFactory(new PropertyValueFactory("myDateAttr"));
And finally, for the shake of clarity this is how you declare the getter in your object class:
public CustomDate getMyDateAttr() { return new CustomDate(myDateAttr.getTime()); //myDateAttr is a java.util.Date }
It took me a while to figure out this due to the fact that it uses java.sql.Date behind the scenes; so hopefully this will save other people some time!
回答3:
I needed to do this recently -
dateAddedColumn.setCellValueFactory( new Callback, ObservableValue>() { @Override public ObservableValue call(TableColumn.CellDataFeatures film) { SimpleStringProperty property = new SimpleStringProperty(); DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy"); property.setValue(dateFormat.format(film.getValue().getCreatedDate())); return property; } });
However - it is a lot easier in Java 8 using Lamba Expressions:
dateAddedColumn.setCellValueFactory( film -> { SimpleStringProperty property = new SimpleStringProperty(); DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy"); property.setValue(dateFormat.format(film.getValue().getCreatedDate())); return property; });
Hurry up with that Java 8 release oracle!
回答4:
Update for Java FX8:
(I'm not sure it is the good place for that answer, but I get the problem in JavaFX8 and some things have changed, like java.time package)
Some differences with the previous answers: I keep the date type on the column, so I need to use both cellValueFactory and cellFactory. I Make a generic reusable method to generate the cellFactory for all date columns. I use java 8 date for java.time package! But the method could be easily reimplemented for java.util.date.
@FXML private TableColumn 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 Callback, TableCell> getDateCell (DateTimeFormatter format) { return column -> { return new TableCell () { @Override protected void updateItem (T item, boolean empty) { super.updateItem (item, empty); if (item == null || empty) { setText (null); } else { setText (format.format (item)); } } }; }; }
The advantages are that:
- 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.)
回答5:
I'd recommend using Java generics to create re-usable column formatter that takes any java.text.Format
. This cuts down on the amount of boilerplate code...
private class ColumnFormatter implements Callback, TableCell> { private Format format; public ColumnFormatter(Format format) { super(); this.format = format; } @Override public TableCell call(TableColumn arg0) { return new TableCell() { @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))); } } }; } }
Examples of usage
birthday.setCellFactory(new ColumnFormatter(new SimpleDateFormat("dd MMM YYYY"))); amplitude.setCellFactory(new ColumnFormatter(new DecimalFormat("0.0dB")));
回答6:
This is what i did and i worked perfectly.
tbColDataMovt.setCellFactory((TableColumn column) -> { return new TableCell() { @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"))); } } }; });
回答7:
An universal solution could be as simple as that:
import javafx.scene.control.TableCell; import javafx.scene.control.TableColumn; import javafx.util.Callback; public interface AbstractConvertCellFactory extends Callback, TableCell> { @Override default TableCell call(TableColumn param) { return new TableCell() { @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); }
And its sample usage:
TableColumn dateCol = new TableColumn("employment date"); dateCol.setCellValueFactory(new PropertyValueFactory("emploumentDateTime")); dateCol.setCellFactory((AbstractConvertCellFactory) value -> new SimpleDateFormat("dd-MM-yyyy").format(value));
回答8:
You can easily pipe Properties of different type and put a formatter or converter in between.
//from my model ObjectProperty valutaProperty; //from my view TableColumn valutaColumn; valutaColumn.setCellValueFactory( cellData -> { SimpleStringProperty property = new SimpleStringProperty(); property.bindBidirectional(cellData.getValue().valutaProperty, new SimpleDateFormat("dd.MM.yyyy", Locale.GERMAN)); return property; });