2016-06-10 3 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

Спасибо. Это была моя ошибка, когда в подписях было слово «Свойство». Что касается другого примечания, когда я заменяю 'crewIdCol.setCellValueFactory (cellData -> cellData.getValue(). CrewIdProperty());' Eclipse говорит мне 'Тип несоответствия: не может преобразовать из IntegerProperty в ObservableValue " –

+0

Я получил это - обнаружил, что Свойства 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())', который делает необходимое конверсия имущества для вас. –

Смежные вопросы