Reputation: 25
I'm stuck with trying to format Long
values in a TableView
with JavaFX.
I have following class to store the rows that I want to display on the table:
import java.text.DecimalFormat;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleLongProperty;
import javafx.beans.property.SimpleStringProperty;
public class DataByCurrencyPairRow {
private DecimalFormat integerFormat = new DecimalFormat("#,###");
private SimpleStringProperty currencyPair = new SimpleStringProperty("");
private SimpleDoubleProperty shareOfTotalVolume = new SimpleDoubleProperty(0);
private SimpleLongProperty totalVolume = new SimpleLongProperty(0);
private SimpleLongProperty currencyBought = new SimpleLongProperty(0);
private SimpleLongProperty currencySold = new SimpleLongProperty(0);
private SimpleLongProperty monthlyAverage = new SimpleLongProperty(0);
public DataByCurrencyPairRow() {
currencyPair.set("");
shareOfTotalVolume.set(0);
totalVolume.set(0);
currencyBought.set(0);
currencySold.set(0);
monthlyAverage.set(0);
}
public String getCurrencyPair() {
return currencyPair.getValue();
}
public void setCurrencyPair(String currencyPair) {
this.currencyPair.setValue(currencyPair);
}
public Long getMonthlyAverage() {
return monthlyAverage.getValue();
}
public void setMonthlyAverage(Long monthlyAverage) {
this.monthlyAverage.setValue(monthlyAverage);
}
public Long getCurrencySold() {
return currencySold.getValue();
}
public void setCurrencySold(Long currencySold) {
this.currencySold.setValue(currencySold);
}
public Long getCurrencyBought() {
return currencyBought.getValue();
}
public void setCurrencyBought(Long currencyBought) {
this.currencyBought.setValue(currencyBought);
}
public Long getTotalVolume() {
return totalVolume.getValue();
}
public void setTotalVolume(Long totalVolume) {
this.totalVolume.setValue(totalVolume);
}
public Double getShareOfTotalVolume() {
return shareOfTotalVolume.getValue();
}
public void setShareOfTotalVolume(Double shareOfTotalVolume) {
this.shareOfTotalVolume.setValue(shareOfTotalVolume);
}
}
Then I have the controller with initialize
method where I have been trying to override the updateItem
method to get the table to show comma as a thousand separator:
public class MainController {
private static final String DEFAULT_TIME_HORIZON = new String("0");
private final NumberFormat integerFormat = new DecimalFormat("#,###");
@FXML
TableView<DataByCurrencyPairRow> tableTransactionsByCurrencyPair;
@FXML
TableColumn<DataByCurrencyPairRow, Long> columnTotal;
@FXML
void initialize() {
columnTotal.setCellFactory(
new Callback<TableColumn<DataByCurrencyPairRow, SimpleLongProperty>, TableCell<DataByCurrencyPairRow, SimpleLongProperty>>() {
@Override
public TableCell<DataByCurrencyPairRow, SimpleLongProperty> call(TableColumn<DataByCurrencyPairRow, SimpleLongProperty> param
) {
return new TableCell<DataByCurrencyPairRow, SimpleLongProperty>() {
@Override
protected void updateItem(SimpleLongProperty item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setText("0");
setStyle("");
} else {
setText(integerFormat.format(item.longValue()));
}
}
};
}
}
);
And this is the method that populates the TableView
:
public void updateByCurrencyPairTable() {
System.out.println("#MainController: Updating data in table view Markets volumes by currency pair");
ObservableList<DataByCurrencyPairRow> data = tableTransactionsByCurrencyPair.getItems();
data.clear();
// Add row items to the table view Markets volume by currency
for (DataByCurrencyPairRow row : customer.getDataByCurrencyPairR12m().getDataByCurrencyPair()) {
data.add(row);
}
}
Please help me by showing how to do this!! I also tried to override the updateItem
method as Long
instead of SimpleLongProperty
and my IDE accepted the code but still the number is not formatted in the table.
Thank you guys in advance!!!
Upvotes: 2
Views: 1624
Reputation: 209684
LongProperty
implements ObservableValue<Number>
, not ObservableValue<Long>
(or ObservableValue<SimpleLongProperty>
). So your table columns need to be of type TableColumn<DataByCurrencyPair, Number>
and your cell factory needs to match those types accordingly.
Here's a simple example of a formatted column with Long
s:
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Random;
import javafx.application.Application;
import javafx.beans.property.LongProperty;
import javafx.beans.property.SimpleLongProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.scene.Scene;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.stage.Stage;
public class TableWithFormattedLong extends Application {
private final NumberFormat integerFormat = new DecimalFormat("#,###");
@Override
public void start(Stage primaryStage) {
TableView<Item> table = new TableView<>();
TableColumn<Item, String> itemColumn = new TableColumn<>("Item");
itemColumn.setCellValueFactory(cellData -> cellData.getValue().nameProperty());
TableColumn<Item, Number> valueColumn = new TableColumn<>("Value");
valueColumn.setCellValueFactory(cellData -> cellData.getValue().valueProperty());
valueColumn.setCellFactory(tc -> new TableCell<Item, Number>() {
@Override
protected void updateItem(Number value, boolean empty) {
super.updateItem(value, empty);
if (value == null || empty) {
setText("");
} else {
setText(integerFormat.format(value));
}
}
});
table.getColumns().add(itemColumn);
table.getColumns().add(valueColumn);
Random rng = new Random();
for (int i = 1 ; i <= 20 ; i++) {
table.getItems().add(new Item("Item "+i, rng.nextLong()));
}
primaryStage.setScene(new Scene(table, 600, 600));
primaryStage.show();
}
public static class Item {
private final StringProperty name = new SimpleStringProperty();
private final LongProperty value = new SimpleLongProperty();
public Item(String name, long value) {
setName(name);
setValue(value);
}
public final StringProperty nameProperty() {
return this.name;
}
public final String getName() {
return this.nameProperty().get();
}
public final void setName(final String name) {
this.nameProperty().set(name);
}
public final LongProperty valueProperty() {
return this.value;
}
public final long getValue() {
return this.valueProperty().get();
}
public final void setValue(final long value) {
this.valueProperty().set(value);
}
}
public static void main(String[] args) {
launch(args);
}
}
Upvotes: 5
Reputation: 51896
There is no need to set the Cellfactory, just set the CellValueFactory.
TableColumn<DataByCurrencyPairRow, String> columnTotal;
columnTotal.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<DataByCurrencyPairRow,String>, ObservableValue<String>>() {
@Override
public ObservableValue<String> call(CellDataFeatures<DataByCurrencyPairRow, String> param) {
DataByCurrencyPairRow value = param.getValue();
return new ReadOnlyStringWrapper(NumberFormat.getNumberInstance(Locale.US).format(123123)); //replace the number with the calculated total
}
});
Upvotes: 0