2015-04-12 174 views
7

我在JavaFX中有TableView。它有一個字段subTotal,該字段取決於字段quantityprice的值。我爲subTotal添加了一個新列。JavaFX Tableview - 列值取決於其他列

我有文本框存在添加一個新行到表。但是,添加按鈕想要爲subTotal設置另一個textfield,但對於小計列來說並不是必須的。

我迄今爲止嘗試:

TableColumn columnCodeProduct = new TableColumn("Product Code"); 
columnCodeProduct.setMinWidth(100); 
columnCodeProduct.setCellValueFactory(new PropertyValueFactory<Data , Integer>("productname ")); 

TableColumn columnProductName = new TableColumn("Product Name"); 
columnProductName.setMinWidth(140); 
columnProductName.setCellValueFactory(new PropertyValueFactory<Data , String>("codeproduct")); 

TableColumn columnPrice = new TableColumn("Price"); 
columnPrice.setMinWidth(100); 
columnPrice.setCellValueFactory(new PropertyValueFactory<Data , Integer>("price")); 

TableColumn columQuantity = new TableColumn("Quantity"); 
columQuantity.setMinWidth(100); 
columQuantity.setCellValueFactory(new PropertyValueFactory<Data , Integer>("quantity")); 


TableColumn columnTotal = new TableColumn("Sub Total"); 
columnTotal.setMinWidth(100); 
columQuantity.setCellValueFactory(new PropertyValueFactory<Data , Integer>("sub")); 

tableData.getColumns().addAll(columnCodeProduct , columnProductName , columnPrice , columQuantity); 

tableData.setItems(data); 


addButton = new Button("Add Item"); 


addButton.setOnAction(new EventHandler<ActionEvent>() { 

    @Override 
    public void handle(ActionEvent event) 
    { 
     if(addproCodeTextfield.getText().isEmpty() || addproNameTextfield.getText().isEmpty() 
      || addPriceTextfield.getText().isEmpty() || quantityTextField.getText().isEmpty()) 
     { 
      System.out.println("Please Add information to all the fields"); 
     } else { 
      data.add(new Data (

          addproCodeTextfield.getText(), 
          addproNameTextfield.getText(), 
       addPriceTextfield.getText(),        
          quantityTextField.getText()));        
      methodTotal(); 
     } 
    } 
}); 

數據類

public class Data 
{ 
    private final SimpleStringProperty codeproduct; 
    private final SimpleStringProperty productname; 
    private final SimpleStringProperty price ; 
    private final SimpleStringProperty quantity; 



    public Data (String code , String proname , String presyo , String quant) 
    { 
     this.codeproduct = new SimpleStringProperty(code); 
     this.productname = new SimpleStringProperty(proname); 
     this.price = new SimpleStringProperty(presyo); 
     this.quantity = new SimpleStringProperty(quant); 

    } 

    public String getcodeProduct() 
    { 
     return codeproduct.get(); 
    } 

    public String getproductName() 
    { 
     return productname.get(); 
    } 

    public String getPrice() 
    { 
     return price.get(); 
    } 

    public String getQuantity() 
    { 
     return quantity.get(); 
    } 

} 

回答

5

您可以從JavaFX的電源好處bind值。如上面所述

幾點需要照顧,同時實施情景的:

  • 的POJO類(在你的情況Data)字段必須有正確的類型。例如,價格和數量必須是SimpleIntegerProperty而不是SimpleStringProperty。這將幫助我們使用Bindings
  • SubTotal字段取決於價格和數量的。達到此目的的最佳方法是綁定subTotalProperty to a multiply Binding of price and quantity

我創建了一個(不那麼)簡單的例子基本可編輯的tableview展現方式。它有額外的功能,如可編輯單元格,您(或他人尋求同樣的問題)可能需要;)

import javafx.application.Application; 
import javafx.beans.binding.Bindings; 
import javafx.beans.binding.NumberBinding; 
import javafx.beans.property.SimpleIntegerProperty; 
import javafx.beans.property.SimpleStringProperty; 
import javafx.collections.FXCollections; 
import javafx.collections.ObservableList; 
import javafx.event.ActionEvent; 
import javafx.event.EventHandler; 
import javafx.geometry.Insets; 
import javafx.scene.Group; 
import javafx.scene.Scene; 
import javafx.scene.control.*; 
import javafx.scene.control.TableColumn.CellEditEvent; 
import javafx.scene.control.cell.PropertyValueFactory; 
import javafx.scene.control.cell.TextFieldTableCell; 
import javafx.scene.layout.HBox; 
import javafx.scene.layout.VBox; 
import javafx.scene.text.Font; 
import javafx.stage.Stage; 
import javafx.util.converter.NumberStringConverter; 

public class TableViewSample extends Application { 

    private TableView<Product> table = new TableView<Product>(); 
    private final ObservableList<Product> data = 
      FXCollections.observableArrayList(
        new Product("Notebook", 10, 12), 
        new Product("Eraser", 20, 12), 
        new Product("Pencil", 30, 12), 
        new Product("Pen", 40, 12), 
        new Product("Glue", 50, 12)); 
    final HBox hb = new HBox(); 

    public static void main(String[] args) { 
     launch(args); 
    } 

    @Override 
    public void start(Stage stage) { 
     Scene scene = new Scene(new Group()); 
     stage.setTitle("Book Store Sample"); 
     stage.setWidth(650); 
     stage.setHeight(550); 

     final Label label = new Label("Book Store"); 
     label.setFont(new Font("Arial", 20)); 

     table.setEditable(true); 


     TableColumn name = new TableColumn("Name"); 
     name.setMinWidth(100); 
     name.setCellValueFactory(
       new PropertyValueFactory<Product, String>("name")); 
     name.setCellFactory(TextFieldTableCell.forTableColumn()); 
     name.setOnEditCommit(
       new EventHandler<CellEditEvent<Product, String>>() { 
        @Override 
        public void handle(CellEditEvent<Product, String> t) { 
         ((Product) t.getTableView().getItems().get(
           t.getTablePosition().getRow()) 
         ).setName(t.getNewValue()); 
        } 
       } 
     ); 


     TableColumn priceCol = new TableColumn("Price"); 
     priceCol.setMinWidth(100); 
     priceCol.setCellValueFactory(
       new PropertyValueFactory<Product, String>("price")); 
     priceCol.setCellFactory(TextFieldTableCell.<Product, Number>forTableColumn(new NumberStringConverter())); 
     priceCol.setOnEditCommit(
       new EventHandler<CellEditEvent<Product, Number>>() { 
        @Override 
        public void handle(CellEditEvent<Product, Number> t) { 
         ((Product) t.getTableView().getItems().get(
           t.getTablePosition().getRow()) 
         ).setPrice(t.getNewValue().intValue()); 
        } 
       } 
     ); 

     TableColumn quantityCol = new TableColumn("Quantity"); 
     quantityCol.setMinWidth(200); 
     quantityCol.setCellValueFactory(
       new PropertyValueFactory<Product, Number>("quantity")); 
     quantityCol.setCellFactory(TextFieldTableCell.<Product, Number>forTableColumn(new NumberStringConverter())); 
     quantityCol.setOnEditCommit(
       new EventHandler<CellEditEvent<Product, Number>>() { 
        @Override 
        public void handle(CellEditEvent<Product, Number> t) { 
         ((Product) t.getTableView().getItems().get(
           t.getTablePosition().getRow()) 
         ).setQuantity(t.getNewValue().intValue()); 
        } 
       } 
     ); 

     TableColumn subTotalCol = new TableColumn("Sub Total"); 
     subTotalCol.setMinWidth(200); 
     subTotalCol.setCellValueFactory(
       new PropertyValueFactory<Product, String>("subTotal")); 


     table.setItems(data); 
     table.getColumns().addAll(name, priceCol, quantityCol, subTotalCol); 

     final TextField addName = new TextField(); 
     addName.setPromptText("Name"); 
     addName.setMaxWidth(name.getPrefWidth()); 
     final TextField addPrice = new TextField(); 
     addPrice.setMaxWidth(priceCol.getPrefWidth()); 
     addPrice.setPromptText("Price"); 
     final TextField addQuantity = new TextField(); 
     addQuantity.setMaxWidth(quantityCol.getPrefWidth()); 
     addQuantity.setPromptText("Quantity"); 

     final Button addButton = new Button("Add"); 
     addButton.setOnAction(new EventHandler<ActionEvent>() { 
      @Override 
      public void handle(ActionEvent e) { 
       data.add(new Product(
         name.getText(), 
         Integer.parseInt(addPrice.getText()), 
         Integer.parseInt(addQuantity.getText()))); 
       addName.clear(); 
       addPrice.clear(); 
       addQuantity.clear(); 
      } 
     }); 

     hb.getChildren().addAll(addName, addPrice, addQuantity, addButton); 
     hb.setSpacing(3); 

     final VBox vbox = new VBox(); 
     vbox.setSpacing(5); 
     vbox.setPadding(new Insets(10, 0, 0, 10)); 
     vbox.getChildren().addAll(label, table, hb); 

     ((Group) scene.getRoot()).getChildren().addAll(vbox); 

     stage.setScene(scene); 
     stage.show(); 
    } 

    public static class Product { 

     private final SimpleStringProperty name; 
     private final SimpleIntegerProperty price; 
     private final SimpleIntegerProperty quantity; 
     private final SimpleIntegerProperty subTotal; 

     private Product(String name, int price, int quantity) { 
      this.name = new SimpleStringProperty(name); 
      this.price = new SimpleIntegerProperty(price); 
      this.quantity = new SimpleIntegerProperty(quantity); 
      this.subTotal = new SimpleIntegerProperty(); 
      NumberBinding multiplication = Bindings.multiply(this.priceProperty(), this.quantityProperty()); 
      this.subTotalProperty().bind(multiplication); 
     } 

     public String getName() { 
      return name.get(); 
     } 

     public SimpleStringProperty nameProperty() { 
      return name; 
     } 

     public void setName(String name) { 
      this.name.set(name); 
     } 

     public int getPrice() { 
      return price.get(); 
     } 

     public SimpleIntegerProperty priceProperty() { 
      return price; 
     } 

     public void setPrice(int price) { 
      this.price.set(price); 
     } 

     public int getQuantity() { 
      return quantity.get(); 
     } 

     public SimpleIntegerProperty quantityProperty() { 
      return quantity; 
     } 

     public void setQuantity(int quantity) { 
      this.quantity.set(quantity); 
     } 

     public int getSubTotal() { 
      return subTotal.get(); 
     } 

     public SimpleIntegerProperty subTotalProperty() { 
      return subTotal; 
     } 

     public void setSubTotal(int subTotal) { 
      this.subTotal.set(subTotal); 
     } 
    } 
} 

截圖

enter image description here

注意 - 我已經定義setCellFactorysetOnCommit到每個列。這是因爲名稱,價格和數量列是editable。如果你不尋求可編輯的財產,你很樂意刪除它們。

+0

謝謝:)它通過怎樣的方式來添加的所有分類彙總工作? – unknown

+0

這實際上可以是一個單獨的問題:) – ItachiUchiha

3

我會像@IchichiUchiha建議的那樣重構你的模型類。如果你覺得你需要保持存儲與String表示的數據,你可以創建一個爲subtotal列綁定:

TableColumn<Data, Number> subtotalColumn = new TableColumn<>("Sub Total"); 
subTotalColumn.setCellValueFactory(cellData -> { 
    Data data = cellData.getValue(); 
    return Bindings.createDoubleBinding(
      () -> { 
       try { 
        double price = Double.parseDouble(data.getPrice()); 
        int quantity = Integer.parseInt(data.getQuantity()); 
        return price * quantity ; 
       } catch (NumberFormatException nfe) { 
        return 0 ; 
       } 
      }, 
      data.priceProperty(), 
      data.quantityProperty() 
    ); 
}); 
+0

謝謝,太容易了! :)我用它來更新一個字符串列,其值是從我的模型中的十六進制字符串中計算出來的。對於每個人都要考慮:我不想爲無效數據顯示有效的0。所以我使用了一個字符串列。如果解析失敗,它可以顯示空字符串或「ERR」。 Afaik,這是不可能的數字列。 – Arjan