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

¿Cómo puedo cambiar el formato de releaseTime? En este momento, llama a un simple toString en el objeto Date.JavaFX Table Cell Formatting

Respuesta

5

que tenía que hacer esto recientemente -

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

Sin embargo - es muchomás fácil en Java 8 utilizando Lamba expresiones:

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

prisa con que Java 8 versiones de Oracle!

+1

Esto funciona muy bien para llenar inicialmente la mesa ... si la propiedad fecha en el modelo cambia más tarde de la SimpleStringProperty no emite una notificación, y la tabla no se actualiza. – Adam

7

Si desea conservar las capacidades de clasificación de su TableColumn, ninguna de las soluciones anteriores es válida: si convierte su Fecha a una Cadena y lo muestra de esa manera en su TableView; la mesa lo ordenará como tal (tan incorrectamente).

La solución que encontré fue la subclasificación de la clase Date para anular el método toString(). Sin embargo, aquí hay una advertencia: el TableView usa java.sql.Date en lugar de java.util.Date; entonces necesitas subclasificar el primero.

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

La tabla llamará a ese método para imprimir la fecha.

Por supuesto, es necesario cambiar también la clase Fecha en la declaración TableColumn a la nueva subclase:

@FXML 
TableColumn<MyObject, CustomDate> myDateColumn; 

Lo mismo cuando se conecta a su atributo de objeto a la columna de la tabla:

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

Y, por último, para el movimiento de la claridad es así como se declara el captador en su clase de objeto:

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

Me tomó un tiempo darme cuenta de esto porque usa java.sql.Date detrás de escena; ¡así que con suerte esto ahorrará a otras personas algo de tiempo!

4

Actualización para FX8 Java:

(no estoy seguro que es el buen lugar para esa respuesta, pero me da el problema en JavaFX8 y algunas cosas han cambiado, al igual que el paquete java.time)

Algunas diferencias con las respuestas anteriores: Guardo el tipo de fecha en la columna, así que tengo que usar tanto cellValueFactory como cellFactory. I Realiza un método reutilizable genérico para generar el cellFactory para todas las columnas de fecha. ¡Uso java 8 date para el paquete java.time! Pero el método podría ser fácilmente reimplementado para 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)); 
     } 
     } 
    }; 
    }; 
} 

Las ventajas son que:

  • La columna se escribe con una "java8 fecha" para evitar el problema especie evoqued por @Jordan
  • El método "getDateCell" es genérico y puede ser utilizado como una función util para todos los tipos Java8 Tiempo (por zonas, locales, etc.)
4

me gustaría recomendar el uso de genéricos de Java para crear reutilizable formateador columna que toma cualquier java.text.Format. Esto reduce la cantidad de código repetitivo ...

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

Ejemplos de uso

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

Esto es lo que hice y funcionó a la perfección.

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

Una solución universal podría ser tan simple como eso:

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

y su uso de la muestra:

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

Puede fácilmente las propiedades de tuberías de distinto tipo y poner un formateador o convertidor entre.

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