2016-07-25 2 views
0

Я застрял в попытке форматирования Long значений в TableView с помощью JavaFX.Формат JavaFX SimpleLongProperty в TableView

У меня есть следующий класс для хранения строк, которые я хочу, чтобы отобразить на столе:

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

    } 

Тогда у меня есть контроллер с initialize способом, где я пытался переопределить метод updateItem, чтобы получить таблицу показать запятую в качестве разделителя:

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

         }; 
        } 
       } 
     ); 

И это метод, который заполнит 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); 
     } 
    } 

Пожалуйста, помогите мне, показав, как это сделать! Я также попытался переопределить метод updateItem как Long вместо SimpleLongProperty, и моя IDE приняла код, но все же номер не отформатирован в таблице.

Спасибо, ребята, заранее!

+0

Что такое значение, которое вы хотите отобразить в этом столбце. В общем, что? – yamenk

+0

Вы не показали, что такое заводская фабрика, или объяснили, что вы на самом деле видите. –

ответ

1

LongProperty реализует ObservableValue<Number>, не ObservableValue<Long> (или ObservableValue<SimpleLongProperty>). Поэтому ваши столбцы таблицы должны быть типа TableColumn<DataByCurrencyPair, Number>, и ваша фабрика ячеек должна соответствовать соответствующим типам.

Вот простой пример отформатированной колонки Long с:

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

Работает как шарм, и вы комментируете решение @ yamenK, помогли понять разницу между cellValueFactory и cellFactory. Спасибо! – Hiltunea

0

Нет необходимости устанавливать Cellfactory, просто установите 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 
      } 
     }); 
+1

Это может работать (в некоторых ограниченных обстоятельствах), но это не очень хорошая практика. Вы эффективно сообщаете столбцу таблицы, что он отображает данные, которые являются «String», что противоречит фактической модели, в которой она является «длинной». Если вы хотите сделать это редактируемым и использовать «TextFieldTableCell», например, он не сможет правильно обновить данные при внесении изменений. Предполагаемое использование заключается в том, что 'cellValueFactory' определяет отображаемые данные, а' cellFactory' определяет * how * для его отображения. Для этого варианта использования «cellFactory» является предполагаемым решением. –