2016-06-10 106 views
2

我知道類似這樣的問題已經被問及在不同的日期,但我會把SSCCE放在這裏,試着簡單地問一下。JavaFX TableView和ObservableList - 如何自動更新表?

我希望能夠更新數據模型,並有任何意見對它自動更新,以便任何更新模型的調用者都不知道當前有哪些視圖。這是我迄今爲止學習/嘗試的內容,並且不呼叫TableView.refresh()它不更新。我錯過了什麼?

main.java:

package application; 

import javafx.application.Application; 
import javafx.beans.property.StringProperty; 
import javafx.collections.FXCollections; 
import javafx.collections.ObservableList; 
import javafx.geometry.Pos; 
import javafx.stage.Stage; 
import javafx.scene.Scene; 
import javafx.scene.control.Button; 
import javafx.scene.control.TableColumn; 
import javafx.scene.control.TableView; 
import javafx.scene.control.cell.PropertyValueFactory; 
import javafx.scene.layout.VBox; 

public class Main extends Application { 
    @Override 
    public void start(Stage stage) { 

     // data 
     ObservableList<Crew> data = FXCollections.observableArrayList(); 
     data.addAll(new Crew(1, "A"), new Crew(2, "B")); 

     // table 
     TableColumn<Crew, Integer> crewIdCol = new TableColumn<Crew, Integer>("Crew ID"); 
     crewIdCol.setCellValueFactory(new PropertyValueFactory<Crew, Integer>("crewId")); 
     crewIdCol.setMinWidth(120); 
     TableColumn<Crew, String> crewNameCol = new TableColumn<Crew, String>("Crew Name"); 
     crewNameCol.setCellValueFactory(new PropertyValueFactory<Crew, String>("crewName")); 
     crewNameCol.setMinWidth(180); 
     TableView<Crew> table = new TableView<Crew>(data); 
     table.getColumns().addAll(crewIdCol, crewNameCol); 
     table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY); 

     // button 
     Button button = new Button(" test "); 
     button.setOnAction(ae -> { 
      // test 
      StringProperty nameProp = data.get(0).crewName(); 
      if(nameProp.get().equals("A")) { 
       data.get(0).setCrewName("foo"); 
       // table.refresh(); 
       System.out.println("foo"); 
      } else { 
       data.get(0).setCrewName("A"); 
       // table.refresh(); 
       System.out.println("A"); 
      } 
     }); 

     VBox box = new VBox(10); 
     box.setAlignment(Pos.CENTER);; 
     box.getChildren().addAll(table, button); 
     Scene scene = new Scene(box); 
     stage.setScene(scene); 
     stage.show(); 
    } 

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

} 

Crew.java

package application; 

import javafx.beans.property.IntegerProperty; 
import javafx.beans.property.SimpleIntegerProperty; 
import javafx.beans.property.SimpleStringProperty; 
import javafx.beans.property.StringProperty; 

public class Crew { 
    private final IntegerProperty crewId = new SimpleIntegerProperty(); 
    private final StringProperty crewName = new SimpleStringProperty(); 

    Crew(int id, String name) { 
     crewId.set(id); 
     crewName.set(name); 
    } 

    public IntegerProperty crewId() { return crewId; } 
    public final int getCrewId() { return crewId.get(); } 
    public final void setCrewId(int id) { crewId.set(id); } 

    public StringProperty crewName() { return crewName; } 
    public final String getCrewName() { return crewName.get(); } 
    public final void setCrewName(String name) { crewName.set(name); } 

} 
+0

您可以擴展您的代碼示例以使其成爲[MCVE]嗎? –

+0

@James_D,我加了crew.java。這應該是完整的。 –

回答

7

模型類Crew具有的屬性訪問方法 「錯誤」 的名稱。如果不按照推薦的方法命名方案,(有點遺留代碼)PropertyValueFactory將無法​​找到的屬性,因此將不能夠觀察他們的變化:

package application; 

import javafx.beans.property.IntegerProperty; 
import javafx.beans.property.SimpleIntegerProperty; 
import javafx.beans.property.SimpleStringProperty; 
import javafx.beans.property.StringProperty; 

public class Crew { 
    private final IntegerProperty crewId = new SimpleIntegerProperty(); 
    private final StringProperty crewName = new SimpleStringProperty(); 

    Crew(int id, String name) { 
     crewId.set(id); 
     crewName.set(name); 
    } 

    public IntegerProperty crewIdProperty() { return crewId; } 
    public final int getCrewId() { return crewId.get(); } 
    public final void setCrewId(int id) { crewId.set(id); } 

    public StringProperty crewNameProperty() { return crewName; } 
    public final String getCrewName() { return crewName.get(); } 
    public final void setCrewName(String name) { crewName.set(name); } 

} 

或者,乾脆直接實現回調:

crewIdCol.setCellValueFactory(cellData -> cellData.getValue().crewIdProperty()); 

在這種情況下,編譯器將確保您使用該屬性的現有方法名稱。

+0

謝謝。這是我的錯誤,在簽名中缺少「Property」這個詞。關於另一個說明,當我替換'crewIdCol.setCellValueFactory(cellData - > cellData.getValue()。crewIdProperty());'Eclipse告訴我「類型不匹配:無法從IntegerProperty轉換爲ObservableValue 」 –

+0

我知道了 - 發現Properties API使用Number而不是Integer ...因此'\t \t TableColumn crewIdCol = new TableColumn (「Crew ID」); \t \t crewIdCol.setCellValueFactory(p - > p.getValue()。crewIdProperty());'做到這一點。 –

+1

是的,正確的:另一個選項是保持它爲'TableColumn '並且執行'crewIdCol.setCellValueFactory(cellData - > cellData.getValue()。crewIdProperty()。asObject())'物業轉換爲你。 –