5

How to make a line of summation in the bottom of the table(TreeTableView - JavaFX or TableView) ? (Sorry for my english) write an example please.

Picture(Totals) for example https://i.stack.imgur.com/uRLTZ.gif

Under each column I put a lable for display SUM.But this is no good for me.

Some FXML `

                                    <AnchorPane fx:id="anchorPaneWithTable" minHeight="0.0" minWidth="0.0" prefHeight="538.0" prefWidth="1275.0">
                                        <children>
                                            <TreeTableView fx:id="treeTableMainStat" prefHeight="386.0" prefWidth="1303.0" showRoot="false" AnchorPane.bottomAnchor="11.0" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="10.0">
                                                <columns>
                                                    <TreeTableColumn fx:id="treeProgramNameCol" editable="false" prefWidth="230.0" resizable="false" text="AP Name" />
                                                    <TreeTableColumn fx:id="treeLastDateCol" editable="false" prefWidth="90.0" resizable="false" text="Last Date" />
                                                    <TreeTableColumn fx:id="treeLoginCol" editable="false" prefWidth="70.0" resizable="false" text="Login" />
                                                    <TreeTableColumn fx:id="treeAffiliateIDCol" editable="false" prefWidth="92.0" resizable="false" text="Affiliate ID" />
                                                    <TreeTableColumn fx:id="treeRawClicksCol" editable="false" resizable="false" text="Raw" />
                                                    <TreeTableColumn fx:id="treeUniqueClicksCol" editable="false" resizable="false" text="Uniq" />
                                                    <TreeTableColumn fx:id="treeSignupCounterCol" editable="false" prefWidth="67.0" resizable="false" text="SignupC" />
                                                    <TreeTableColumn fx:id="treeSignupMoneyCol" editable="false" minWidth="3.0" prefWidth="77.0" resizable="false" text="SignupM" />
                                                    <TreeTableColumn fx:id="treeRebillCounterCol" editable="false" minWidth="0.0" prefWidth="66.0" resizable="false" text="RebillC" />
                                                    <TreeTableColumn fx:id="treeRebillMoneyCol" editable="false" prefWidth="78.0" resizable="false" text="RebillM" />
                                                    <TreeTableColumn fx:id="treeRefundChargebackCounterCol" editable="false" prefWidth="105.0" resizable="false" text="R/Ch Counter" />
                                                    <TreeTableColumn fx:id="treeRefundChargebackMoneyCol" editable="false" prefWidth="104.0" resizable="false" text="R/Ch Money" />
                                                    <TreeTableColumn fx:id="treeTotalMoneyCol" editable="false" minWidth="0.0" prefWidth="110.0" resizable="false" text="Total Money" />
                                                </columns>
                                                <contextMenu>
                                                    <ContextMenu>
                                                        <items>
                                                            <MenuItem mnemonicParsing="false" onAction="#handleAddNewAffiliateProgram" text="Add new AP" />
                                                            <MenuItem mnemonicParsing="false" text="Unspecified Action" />
                                                            <MenuItem mnemonicParsing="false" text="Unspecified Action" />
                                                            <MenuItem mnemonicParsing="false" onAction="#handleDeleteAffiliateProgram" text="Delete AP" />
                                                            <SeparatorMenuItem mnemonicParsing="false" />
                                                            <MenuItem mnemonicParsing="false" onAction="#handleEditAP" text="Properties" />
                                                        </items>
                                                    </ContextMenu>
                                                </contextMenu>
                                            </TreeTableView>
                                            <ProgressIndicator fx:id="refreshingIndicator" layoutX="478.0" layoutY="124.0" prefHeight="250.0" prefWidth="374.0" progress="-1.0" AnchorPane.leftAnchor="478.0" AnchorPane.topAnchor="124.0" />
                                        </children>
                                    </AnchorPane>
                                </content>
                            </Tab>
                            <Tab closable="false" text="Empty Tab">
                                <content>
                                    <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" visible="false" />
                                </content>
                            </Tab>
                        </tabs>
                    </TabPane>
                    <HBox prefHeight="35.0">
                        <children>
                            <Label fx:id="apNameLab" prefHeight="30.0" prefWidth="229.0" text="Label" />
                            <Separator orientation="VERTICAL" prefHeight="200.0" />
                            <Label fx:id="lastDateLab" prefHeight="30.0" prefWidth="85.0" text="LastDate" />
                            <Separator orientation="VERTICAL" prefHeight="200.0" />
                            <Label fx:id="loginLab" prefHeight="30.0" prefWidth="64.0" text="Login" />
                            <Separator orientation="VERTICAL" prefHeight="200.0" />
                            <Label fx:id="affilIdLab" prefHeight="30.0" prefWidth="86.0" text="AffID" />
                            <Separator orientation="VERTICAL" prefHeight="200.0" />
                            <Label fx:id="rawLab" prefHeight="30.0" prefWidth="74.0" text="rawLab" />
                            <Separator orientation="VERTICAL" prefHeight="200.0" />
                            <Label fx:id="uniqLab" prefHeight="30.0" prefWidth="74.0" text="uniqLab" />
                            <Separator orientation="VERTICAL" prefHeight="200.0" />
                            <Label fx:id="signCLab" prefHeight="30.0" prefWidth="61.0" text="SignCLab" />
                            <Separator orientation="VERTICAL" prefHeight="200.0" />
                            <Label fx:id="signMLab" prefHeight="30.0" prefWidth="71.0" text="SignMLab" />
                            <Separator orientation="VERTICAL" prefHeight="200.0" />
                            <Label fx:id="rebillCLab" prefHeight="30.0" prefWidth="61.0" text="RebillCLab" />
                            <Separator orientation="VERTICAL" prefHeight="200.0" />
                            <Label fx:id="rebillMLab" prefHeight="30.0" prefWidth="72.0" text="RebillMLab" />
                            <Separator orientation="VERTICAL" prefHeight="200.0" />
                            <Label fx:id="rChCountLab" prefHeight="30.0" prefWidth="99.0" text="RChCounLab" />
                            <Separator orientation="VERTICAL" prefHeight="200.0" />
                            <Label fx:id="rChMonLab" prefHeight="30.0" prefWidth="98.0" text="RChMonLab" />
                            <Separator orientation="VERTICAL" prefHeight="200.0" />
                            <Label fx:id="totalLab" prefHeight="30.0" prefWidth="110.0" text="TotalLab" />
                        </children>
                        <padding>
                            <Insets left="10.0" />
                        </padding>
                    </HBox>
                </children>
            </VBox>`

Binding labels to columns

//TreeView_Begin
@FXML
private TreeTableView<APDataFromDB> treeTableMainStat;
@FXML
private TreeTableColumn<APDataFromDB, Integer> treeProgramNameCol;
@FXML
private TreeTableColumn<APDataFromDB, Integer> treeLastDateCol;
@FXML
private TreeTableColumn<APDataFromDB, Integer> treeLoginCol;
@FXML
private TreeTableColumn<APDataFromDB, Integer> treeAffiliateIDCol;
@FXML
private TreeTableColumn<APDataFromDB, Integer> treeRawClicksCol;
@FXML
private TreeTableColumn<APDataFromDB, Integer> treeUniqueClicksCol;
@FXML
private TreeTableColumn<APDataFromDB, Integer> treeSignupCounterCol;
@FXML
private TreeTableColumn<APDataFromDB, Double> treeSignupMoneyCol;
@FXML
private TreeTableColumn<APDataFromDB, Integer> treeRebillCounterCol;
@FXML
private TreeTableColumn<APDataFromDB, Double> treeRebillMoneyCol;
@FXML
private TreeTableColumn<APDataFromDB, Integer> treeRefundChargebackCounterCol;
@FXML
private TreeTableColumn<APDataFromDB, Double> treeRefundChargebackMoneyCol;
@FXML
private TreeTableColumn<APDataFromDB, Double> treeTotalMoneyCol;
//TreeView_End


@FXML
Label apNameLab = new Label();
@FXML
Label lastDateLab = new Label();
@FXML
Label loginLab = new Label();
@FXML
Label affilIdLab = new Label();
@FXML
Label rawLab = new Label();
@FXML
Label uniqLab = new Label();
@FXML
Label signCLab = new Label();
@FXML
Label signMLab = new Label();
@FXML
Label rebillCLab = new Label();
@FXML
Label rebillMLab = new Label();
@FXML
Label rChCountLab = new Label();
@FXML
Label rChMonLab = new Label();
@FXML
Label totalLab = new Label();

        @FXML
    private void initialize() throws SQLException {

        final String pattern = "yyyy-MM-dd";

        datePickerStart.setValue(LocalDate.now());
        datePickerEnd.setValue(LocalDate.now());
        allDownloadsProgressBar.setProgress(0);
        refreshingIndicator.setVisible(false);

        StringConverter stringConverter = new StringConverter<LocalDate>() {
            DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern(pattern);

            @Override
            public String toString(LocalDate date) {
                if (date != null) {
                    return dateFormatter.format(date);
                } else {
                    return "";
                }
            }

            @Override
            public LocalDate fromString(String string) {
                if (string != null && !string.isEmpty()) {
                    return LocalDate.parse(string, dateFormatter);
                } else {
                    return null;
                }
            }
        };
        datePickerStart.setConverter(stringConverter);
        datePickerStart.setPromptText(pattern.toLowerCase());
        datePickerEnd.setConverter(stringConverter);
        datePickerEnd.setPromptText(pattern.toLowerCase());

        // устанавливаем тип и значение которое должно хранится в колонке
        //TreeView_begin
        treeProgramNameCol.setCellValueFactory(new TreeItemPropertyValueFactory<>("apName"));
        treeLastDateCol.setCellValueFactory(new TreeItemPropertyValueFactory<>("lastDate"));
        treeLoginCol.setCellValueFactory(new TreeItemPropertyValueFactory<>("login"));
        treeAffiliateIDCol.setCellValueFactory(new TreeItemPropertyValueFactory<>("affiliateID"));
        treeRawClicksCol.setCellValueFactory(new TreeItemPropertyValueFactory<>("raw"));
        treeUniqueClicksCol.setCellValueFactory(new TreeItemPropertyValueFactory<>("uniq"));
        treeSignupCounterCol.setCellValueFactory(new TreeItemPropertyValueFactory<>("signupCounter"));
        treeSignupMoneyCol.setCellValueFactory(new TreeItemPropertyValueFactory<>("signup"));
        treeRebillCounterCol.setCellValueFactory(new TreeItemPropertyValueFactory<>("rebillCounter"));
        treeRebillMoneyCol.setCellValueFactory(new TreeItemPropertyValueFactory<>("rebillMoney"));
        treeRefundChargebackCounterCol.setCellValueFactory(new TreeItemPropertyValueFactory<>("refundChargebackCounter"));
        treeRefundChargebackMoneyCol.setCellValueFactory(new TreeItemPropertyValueFactory<>("refundChargebackMoney"));
        treeTotalMoneyCol.setCellValueFactory(new TreeItemPropertyValueFactory<>("totalMoney"));

        // заполняем таблицу данными

        //        Platform.runLater(new Runnable() {
//            @Override
//            public void run() {
//
//            }
//        });
        new Thread(new Runnable() {
            @Override
            public void run() {
                buildTreeOfStatsFromDB();
                //Binding
                apNameLab.prefWidthProperty().bind(treeProgramNameCol.widthProperty().multiply(1));
                lastDateLab.prefWidthProperty().bind(treeLastDateCol.widthProperty().multiply(1));
                loginLab.prefWidthProperty().bind(treeLoginCol.widthProperty().multiply(1));
                affilIdLab.prefWidthProperty().bind(treeAffiliateIDCol.widthProperty().multiply(1));
                rawLab.prefWidthProperty().bind(treeRawClicksCol.widthProperty().multiply(1));
                uniqLab.prefWidthProperty().bind(treeUniqueClicksCol.widthProperty().multiply(1));
                signCLab.prefWidthProperty().bind(treeSignupCounterCol.widthProperty().multiply(1));
                signMLab.prefWidthProperty().bind(treeSignupMoneyCol.widthProperty().multiply(1));
                rebillCLab.prefWidthProperty().bind(treeRebillCounterCol.widthProperty().multiply(1));
                rebillMLab.prefWidthProperty().bind(treeRebillMoneyCol.widthProperty().multiply(1));
                rChCountLab.prefWidthProperty().bind(treeRefundChargebackCounterCol.widthProperty().multiply(1));
                rChMonLab.prefWidthProperty().bind(treeRefundChargebackMoneyCol.widthProperty().multiply(1));
                totalLab.prefWidthProperty().bind(treeTotalMoneyCol.widthProperty().multiply(1));

                getSumLabel();

            }
        }).start();

//        buildTreeOfStatsFromDB();


        // Enable arrow keys for delete AP
        treeTableMainStat.addEventFilter(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() {
            @Override
            public void handle(KeyEvent keyEvent) {
                if (keyEvent.getCode() == KeyCode.Y && keyEvent.isControlDown()) {
                    handleDeleteAffiliateProgram();
                    keyEvent.consume();
                }
            }
        });
    }

Get all SUMs

private void getSumLabel() {
        long rawHitsSum = 0;
        long uniqHitsSum = 0;
        long signCountSum = 0;
        double signMoneySum = 0;
        long rebillCountSum = 0;
        double rebillMoneySum = 0;
        long rChCountSum = 0;
        double rChMoneySum = 0;
        double totalMoneySum = 0;

        ObservableList<TreeItem<APDataFromDB>> allData = rootItem.getChildren();
        for (TreeItem<APDataFromDB> apDataFromDBTreeItem : allData) {
            rawHitsSum += apDataFromDBTreeItem.getValue().getRaw();
            uniqHitsSum += apDataFromDBTreeItem.getValue().getUniq();
            signCountSum += apDataFromDBTreeItem.getValue().getSignupCounter();
            signMoneySum += apDataFromDBTreeItem.getValue().getSignup();
            rebillCountSum += apDataFromDBTreeItem.getValue().getRebillCounter();
            rebillMoneySum += apDataFromDBTreeItem.getValue().getRebillMoney();
            rChCountSum += apDataFromDBTreeItem.getValue().getRefundChargebackCounter();
            rChMoneySum += apDataFromDBTreeItem.getValue().getRefundChargebackMoney();
            totalMoneySum += apDataFromDBTreeItem.getValue().getTotalMoney();
        }

        final long finalRawHitsSum = rawHitsSum;
        final long finalUniqHitsSum = uniqHitsSum;
        final long finalSignCountSum = signCountSum;
        final long finalSignCountSum1 = signCountSum;
        final long finalRebillCountSum = rebillCountSum;
        final double finalRebillMoneySum = rebillMoneySum;
        final long finalRChCountSum = rChCountSum;
        final double finalRChMoneySum = rChMoneySum;
        final double finalTotalMoneySum = totalMoneySum;
        Platform.runLater(new Runnable() {
            @Override
            public void run() {
                rawLab.setText(String.valueOf(finalRawHitsSum));
                uniqLab.setText(String.valueOf(finalUniqHitsSum));
                signCLab.setText(String.valueOf(finalSignCountSum1));
                signMLab.setText(String.valueOf(finalSignCountSum));
                rebillCLab.setText(String.valueOf(finalRebillCountSum));
                rebillMLab.setText(String.valueOf(finalRebillMoneySum));
                rChCountLab.setText(String.valueOf(finalRChCountSum));
                rChMonLab.setText(String.valueOf(finalRChMoneySum));
                totalLab.setText(String.valueOf(finalTotalMoneySum));
            }
        });
        System.out.println(rawHitsSum);
    }

Adrenal1ne
  • 202
  • 3
  • 14

4 Answers4

7

In JavaFX it's like in Swing: The quickest way to do it is to create a 2nd table.

You can take a look at a summary table sample code on this gist.

Screenshot:

enter image description here

Roland
  • 18,114
  • 12
  • 62
  • 93
  • Thank you :)how to lock(blocked) column? the user does not have to move them – Adrenal1ne May 28 '15 at 14:26
  • That was [already handled on SO](http://stackoverflow.com/questions/14116792/how-to-disable-the-reordering-of-table-columns-in-tableview). – Roland May 28 '15 at 14:31
  • Very nice. Thank you friend :) – Adrenal1ne May 28 '15 at 16:53
  • I try to make your code in fxml. Сan not add scrollBar synchronization.This part ---> // synchronize scrollbars (must happen after table was made visible) ScrollBar mainTableHorizontalScrollBar = findScrollBar( mainTable, Orientation.HORIZONTAL); ScrollBar sumTableHorizontalScrollBar = findScrollBar( sumTable, Orientation.HORIZONTAL); – Adrenal1ne May 29 '15 at 11:11
  • don't worry - I made this :) – Adrenal1ne May 29 '15 at 16:25
  • @Roland Please update your code as I found a bug: `sumColumn.visibleProperty().bindBidirectional(mainColumn.visibleProperty())`; instead of `sumColumn.visibleProperty().bind(mainColumn.visibleProperty());` Making a column invisible and then visible again would cause some exceptions on binding – trilogy Apr 02 '19 at 15:03
5

I would do this by implementing a TransformationList that adds an extra element at the end of the actual data list.

In my example I have a TableView displaying LineItems (my model class), so my TransformationList implementation looks like:

public class LineItemListWithTotal extends TransformationList<LineItem, LineItem> {

    private final TotalLine totalLine ;
    
    protected LineItemListWithTotal(
            ObservableList<? extends LineItem> source) {
        super(source);
        totalLine = new TotalLine(source);
    }

    @Override
    protected void sourceChanged(Change<? extends LineItem> c) {
        
        // no need to modify change: 
        // indexes generated by the source list will match indexes in this list
        
        fireChange(c);
    }

    @Override
    public int getSourceIndex(int index) {
        if (index < getSource().size()) {
            return index ;
        }
        return -1 ;
    }

    @Override
    public int getViewIndex(int index) {
        return index ;
    }

    @Override
    public LineItem get(int index) {
        if (index < getSource().size()) {
            return getSource().get(index);
        } else if (index == getSource().size()) {
            return totalLine ;
        } else throw new ArrayIndexOutOfBoundsException(index);
    }

    @Override
    public int size() {
        return getSource().size() + 1 ;
    }
    
}

You might find you need a special subclass of your model class in order to make this work easily (in this example I subclassed LineItem with TotalLine).

Create your actual data list with an extractor that retrieves the properties you need to observe when calculating the "total" line (i.e. the properties on which that line depends):

ObservableList<LineItem> items = FXCollections.observableArrayList(item -> 
    new Observable[] {item.totalProperty()});

and then use that to create the TransformationList and pass the TransformationList to the control:

table.setItems(new LineItemListWithTotal(items));

I manage the observer for the total line in the special subclass implementing the total:

public class TotalLine extends LineItem {
    
    private final ReadOnlyObjectWrapper<Double> total = new ReadOnlyObjectWrapper<>();
    
    public TotalLine(ObservableList<? extends LineItem> items) {
        super("Total", null, null);
        
        total.bind(Bindings.createObjectBinding(() -> 
                items.stream().collect(Collectors.summingDouble(LineItem::getTotal)), items));
    }
    
    @Override
    public ReadOnlyObjectProperty<Double> totalProperty() {
        return total ;
    }
}

This way, when anything is added to or removed from the original data list, or if any of the properties in the extractor for any of the elements change, the total for the total line is recomputed.

Complete example is here

enter image description here

James_D
  • 201,275
  • 16
  • 291
  • 322
  • Do you know how to make the summary always visible? – Roland May 28 '15 at 14:47
  • No... that would be useful :). The two-tables approach will do that, but this feels a bit more natural somehow. – James_D May 28 '15 at 14:59
  • Very good idea but need "always viseble" mode :) Thank you man ;) – Adrenal1ne May 28 '15 at 16:54
  • Fair enough. If and when https://javafx-jira.kenai.com/browse/RT-19454 is ever addressed, this would be a possible option for you. – James_D May 28 '15 at 17:01
  • @James_D Does this make the Total line get sorted with all other elements, if one re-sorts the list by a table column, or does the Total line stay at the bottom? – ulrich Aug 22 '16 at 07:08
  • great ideas, but how this can be done with filtredlist ?? – abdou amer Jan 03 '19 at 10:29
  • @James_D Java 9 + has this error : `LineItemListWithTotal is not abstract and does not override abstract method getViewIndex(int) in javafx.collections.transformation.TransformationList` Are you able to update your code to override the `getViewIndex` method? – trilogy Jul 07 '22 at 17:57
  • @trilogy Nothing is reordered, so `getViewIndex(int index)` should just return `index`. It looks like they added that method after making the class public, which is a non-back-compatible change. – James_D Jul 07 '22 at 18:10
  • @James_D the docs say this : "the index of the element in this list if it is contained in this list or negative value otherwise" which is actually weird because your `getSourceIndex` does the same thing in your code... so maybe they switched the two out? but the docs say this for `getSourceIndex` : "the index of the element's origin in the source list" they don't make mention of a negative value... https://openjfx.io/javadoc/17/javafx.base/javafx/collections/transformation/TransformationList.html – trilogy Jul 07 '22 at 18:18
  • 1
    @trilogy Huh? Nothing here is reordered, so for almost all elements the index in the "view" (the transformed list) is the index in the source, and vice-versa.. The only exception is the total line, which only appears in the view and not in the source, so `getSourceIndex()` should return `-1` for that item. Everything else is just the identity mapping. – James_D Jul 07 '22 at 18:23
  • @James_D ok got it. – trilogy Jul 07 '22 at 18:28
0

I would rather wrap the TableView inside a GridPane (assuming that it is placed in the first row), and then add an HBox wrapped inside a VBox in the second row. For the HBox, I simply add a Label, a Region, and a TextField. Below are snippets from the final FXML:

<VBox fx:id="totalPriceSection" alignment="CENTER_LEFT" GridPane.rowIndex="2">
    <children>
        <HBox alignment="CENTER_RIGHT" spacing="5.0" VBox.vgrow="ALWAYS">
            <children>
                <Label fx:id="labelInvoiceTotal" text="Total"></Label>
                <Region HBox.hgrow="ALWAYS" />
                <TextField fx:id="tfTotalPrice" editable="false" text="0,00 €">
                </TextField>
            </children>
        </HBox>
    </children>
</VBox>

Now assuming the following snippets for my table:

<TableView fx:id="tableView" GridPane.rowIndex="1">
   <columns>
       <TableColumn fx:id="colId" text="id"/>
       <TableColumn fx:id="colProduct" text="Product Name"/>
       <TableColumn fx:id="colSinglePrice" text="Single Price"/>
       <TableColumn fx:id="colAmount" text="Selected Amount"/>
       <TableColumn fx:id="colTotalPrice" text="Total Price"/>
   </columns>
</TableView>

Later in my controller class, after populating the table using Cell Factories, I adjust the summary row's width according to the table width, as follows:

    public void initialize(URL url, ResourceBundle rb) {
        initMatTable();
        createWidthBindings();
        adjustSummaryRowWidth(); 
    }   

    private void initMatTable() {...}

    private void createWidthBindings()
    {
        widthBinding = Bindings.createDoubleBinding(() -> {
                    double idColWidth = colId.getWidth();
                    double prodColWidth = colProduct.getWidth();
                    double singlePriceColWidth = colSinglePrice.getWidth();
                    double amountColWidth = colAmount.getWidth();
                    double totalColWidth = colTotalPrice.getWidth();
                    return idColWidth + prodColWidth + singlePriceColWidth +
                            amountColWidth + totalColWidth;
                }, 
                idColWidth.widthProperty(),
                prodColWidth.widthProperty(),
                singlePriceColWidth.widthProperty(),
                amountColWidth.widthProperty(),
                totalColWidth.widthProperty());
    }

    private void adjustSummaryRowWidth()
    {
        tfTotalPrice.minWidthProperty().bind(colTotalPrice.widthProperty());
        tfTotalPrice.prefWidthProperty().bind(colTotalPrice.widthProperty());
        tfTotalPrice.maxWidthProperty().bind(colTotalPrice.widthProperty());

        totalPriceSection.minWidthProperty().bind(widthBinding);
        totalPriceSection.prefWidthProperty().bind(widthBinding);
        totalPriceSection.maxWidthProperty().bind(widthBinding);
    }

The main idea here is to ensure the total price remains consistently visible and separate from the main table body.

sciPher80s
  • 23
  • 4
-1

EDIT :Not the answer of the question. I misunderstood the problem.


I don't have an example but I can explain you one way of doing it.

  • Use a "TableView"
  • Each column should be a "TableColumn". This "TableColumn" should be related to an "ObsverbableList" with :

    YourColumn.setCellValueFactory(
            cellData ->CellData.getValue().yourObservableList.yourFloatProperty());
    
  • The numbers inside your list should be "FloatProperty".

  • Set a listener on all of them except the last one. (You can do this in a loop)
    • Each listener should call your sum function. This function should calculate the last element of your list = the sum of the other element in the list
    • The "TableView" will automatically update it self.
  • I known how to add data in TreeTableView and how to create simple treeTable. But I do not understant how to create table with "Totals" line. – Adrenal1ne May 28 '15 at 13:38
  • Adrenal1ne, the listeners will triger the sum function each time an element change in your column. This function should modify the last element of you TableColumn. You probably can use the same tools with the TreeTableView. – Gianluca Ricciardelli May 28 '15 at 13:56
  • Если бы я знал английский хорошо, то было бы проще , а так ... Gianluca Ricciardelli , how to make only table WITH Total line. I want draw a table in fxml. A beautiful table WITH TOTAL LINE. :)))))))))))) I can count the amount in column. I need only "draw" of table. :)) – Adrenal1ne May 28 '15 at 14:00
  • Ok, sorry I misunderstood you ! – Gianluca Ricciardelli May 28 '15 at 15:01