Asif Ali
Asif Ali

Reputation: 1

How to add TableView footer in JavaFx TableView

I am stuck on how to add table footer or column footer in JavaFX TableView. I am looking to add a TableView which will show purchased items with quantities and sells price in columns and total items count and total sum at the TableView footer. I looked at various resources, but could not find footer property associated with TableView. Any idea how to do it?

What I am looking to achieve

Model Class

    package javafxapplication8;
    
    public class TestModel {
    
        private String itemName = null;
    
        private int pricePerUnit = 0;
    
        private double quantity = 0.0;
    
        private double amount = 0.0;
    
        public TestModel() {
        }
    
        public TestModel(String argitemName, int argpricePerUnit, double argquantity, double argamount) {
            itemName = argitemName;
            pricePerUnit = argpricePerUnit;
            quantity = argquantity;
            amount = argamount;
    
        }
    
        public void setItemName(String argitemName) {
            itemName = argitemName;
        }
    
        public void setPricePerUnit(int argpricePerUnit) {
            pricePerUnit = argpricePerUnit;
        }
    
        public void setQuantity(double argquantity) {
            quantity = argquantity;
        }
    
        public void setAmount(double argamount) {
            amount = argamount;
        }
    
        public String getItemName() {
            return itemName;
        }
    
        public int getPricePerUnit() {
            return pricePerUnit;
        }
    
        public double getQuantity() {
            return quantity;
        }
    
        public double getAmount() {
            return amount;
        }
    
        @Override
        public String toString() {
            return this.itemName + "" + this.pricePerUnit + "" + this.quantity + "" + this.amount;
        }
    
    }

XML Code

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>

<AnchorPane id="AnchorPane" fx:id="anchor" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1" fx:controller="javafxapplication8.TVCTestModel">
    <children>
        <VBox prefHeight="564.0" prefWidth="857.0">
            <children>
                <HBox alignment="BOTTOM_LEFT" prefHeight="100.0" prefWidth="1613.0" spacing="20.0" />            
                <BorderPane prefHeight="695.0" prefWidth="1618.0">
                    <center>
                        <VBox prefHeight="544.0" prefWidth="772.0">
                            <children>
                                <HBox prefHeight="65.0" prefWidth="1618.0" />
                                <HBox prefHeight="426.0" prefWidth="857.0">
                                    <children>
                                        <HBox alignment="CENTER" prefHeight="225.0" prefWidth="857.0">
                                            <children>                  
                                                <TableView fx:id="myTableView" prefHeight="419.0" prefWidth="816.0">
                                                    <columns>
                                                        <TableColumn fx:id="itemName" prefWidth="200.0" text="Item Name" />
                                                        <TableColumn fx:id="pricePerUnit" prefWidth="200.0" text="Price Per Unit" />
                                                        <TableColumn fx:id="quantity" prefWidth="200.0" text="Quantity" />
                                                        <TableColumn fx:id="amount" prefWidth="200.0" text="Amount" />
                                                    </columns>
                                                </TableView>
                                            </children>
                                        </HBox>
                                    </children>
                                </HBox>
                            </children>
                        </VBox>              
                    </center>
                    <bottom>

                    </bottom>
                </BorderPane>         
            </children>
        </VBox>
    </children>
</AnchorPane>

Controller Class

package javafxapplication8;

import java.net.URL;

import java.util.ResourceBundle;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;

import javafx.fxml.FXML;
import javafx.fxml.Initializable;

import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.AnchorPane;

public class TVCTestModel implements Initializable {

    @FXML
    private TableColumn<TestModel, String> itemName;

    @FXML
    private TableColumn<TestModel, Integer> pricePerUnit;

    @FXML
    private TableColumn<TestModel, Double> quantity;

    @FXML
    private TableColumn<TestModel, Double> amount;
    @FXML
    private TableView<TestModel> myTableView;
    public ObservableList<TestModel> objList = FXCollections.observableArrayList();
    @FXML
    private AnchorPane anchor;
    private static TestModel curTestModel;

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        this.itemName.setCellValueFactory(new PropertyValueFactory<>("itemName"));
        this.pricePerUnit.setCellValueFactory(new PropertyValueFactory<>("pricePerUnit"));
        this.quantity.setCellValueFactory(new PropertyValueFactory<>("quantity"));
        this.amount.setCellValueFactory(new PropertyValueFactory<>("amount"));

        objList.add(new TestModel("Item 1", 10, 4, 400));
        objList.add(new TestModel("Item 2", 20, 5, 1000));
        objList.add(new TestModel("Item 3", 30, 6, 1800));
        objList.add(new TestModel("Item 4", 400, 7, 2800));
        System.out.println(objList.size());
        myTableView.setItems(objList);
    }

}

MainMethod Class

   package javafxapplication8;
    
    import java.io.IOException;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    import javafx.application.Application;
    import javafx.fxml.FXMLLoader;
    import javafx.scene.Parent;
    import javafx.scene.Scene;
    import javafx.stage.Stage;
    
    public class JavaFXApplication8 extends Application {
    
        @Override
        public void start(Stage primaryStage) {
    
            try {
                Parent root = FXMLLoader.load(getClass().getResource("TVCTestModel.fxml"));
                Scene scene = new Scene(root);
                primaryStage.setScene(scene);
                primaryStage.show();
    
            } catch (IOException ex) {
                Logger.getLogger(JavaFXApplication8.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    
    }

Upvotes: -2

Views: 1148

Answers (1)

trashgod
trashgod

Reputation: 205875

Your updated question was reopened, and the image provided suggests that, instead of a footer, you want two summary fields. As your table is not editable, a simple approximation is illustrated here—add two labels to the view, and iterate the table's model in the controller to establish the localized result:

image

TVCTestModel.fxml:

…
<bottom>
    <HBox alignment="CENTER_RIGHT" style="-fx-spacing: 5px;">
        <children>
            <Label fx:id="labelQ"/>
            <Label fx:id="labelA"/>
        </children>
    </HBox>
</bottom>
…

TVCTestModel.java

@FXML private Label labelQ;
@FXML private Label labelA;

@Override
public void initialize(URL url, ResourceBundle rb) {
    …
    double sumQuantity = 0;
    double sumAmout = 0;
    for (TestModel o : objList) {
        sumQuantity += o.getQuantity();
        sumAmout += o.getAmount();
    }
    labelQ.setText("Quantity: "
        + NumberFormat.getNumberInstance().format(sumQuantity));
    labelA.setText("Amount: "
       + NumberFormat.getCurrencyInstance().format(sumAmout));
}

If you later decide to make your table editable, as shown here, you should consider these modifications:

  • Migrate to observable properties in your model class, as shown here, here and here.

  • To minimize arithmetic errors, derive the amount value, as shown here, or use a custom cell factory, as shown here.

  • Create your ObservableList model with an extractor, as shown here and here; your extractor would include properties for quantity and amount; your controller could then update the summary field in a ListChangeListener.

Upvotes: 2

Related Questions