2014-02-11 3 views
3

Предположим, что у меня есть коллекция карты:JavaFX: Добавление строк в TableView с HashMap связывания

ObserableHashMap<K,V> map = FXCollections.observableHashMap(); 

Я положил 1 запись в эту карту во FXML инициализации контроллера, а затем обернуть его как ObservableList:

ObservableList<ObserableHashMap.Entry<K,V>> list = FXCollections.observableArrayList(map.entrySet()); 

затем setitems для моего tableView.setItems(list);

Все нормально, когда я запускаю это приложение JavaFX и 1 запись показывает.

Вопрос в том, что:

Когда я добавляю больше записей позже к моей карте, мой TableView не обновит эти записи.

Как я могу связать динамическую коллекцию карт с моими TableView?

Благодаря

+0

Кстати, все прекрасно, если я изменил карту ObserableHashMap на ObserableArrayList – user2196346

+0

Для получения более подробной информации, пожалуйста, добавьте код, демонстрирующий проблему. Трудно понять, какова ваша проблема только с тремя строками кода. –

ответ

1

Вы можете привязать карту непосредственно к TableView, рассмотрим следующий пример из документации JavaFX:

import java.util.HashMap; 
import java.util.Map; 
import javafx.application.Application; 
import javafx.collections.FXCollections; 
import javafx.collections.ObservableList; 
import javafx.geometry.Insets; 
import javafx.scene.Group; 
import javafx.scene.Scene; 
import javafx.scene.control.Label; 
import javafx.scene.control.TableCell; 
import javafx.scene.control.TableColumn; 
import javafx.scene.control.TableView; 
import javafx.scene.control.cell.MapValueFactory; 
import javafx.scene.control.cell.TextFieldTableCell; 
import javafx.scene.layout.VBox; 
import javafx.scene.text.Font; 
import javafx.stage.Stage; 
import javafx.util.Callback; 
import javafx.util.StringConverter; 

public class TableViewSample extends Application { 

    public static final String Column1MapKey = "A"; 
    public static final String Column2MapKey = "B"; 

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

    @Override 
    public void start(Stage stage) { 
     Scene scene = new Scene(new Group()); 
     stage.setTitle("Table View Sample"); 
     stage.setWidth(300); 
     stage.setHeight(500); 

     final Label label = new Label("Student IDs"); 
     label.setFont(new Font("Arial", 20)); 

     TableColumn<Map, String> firstDataColumn = new TableColumn<>("Class A"); 
     TableColumn<Map, String> secondDataColumn = new TableColumn<>("Class B"); 

     firstDataColumn.setCellValueFactory(new MapValueFactory(Column1MapKey)); 
     firstDataColumn.setMinWidth(130); 
     secondDataColumn.setCellValueFactory(new MapValueFactory(Column2MapKey)); 
     secondDataColumn.setMinWidth(130); 

     TableView table_view = new TableView<>(generateDataInMap()); 

     table_view.setEditable(true); 
     table_view.getSelectionModel().setCellSelectionEnabled(true); 
     table_view.getColumns().setAll(firstDataColumn, secondDataColumn); 
     Callback<TableColumn<Map, String>, TableCell<Map, String>> 
      cellFactoryForMap = new Callback<TableColumn<Map, String>, 
       TableCell<Map, String>>() { 
        @Override 
        public TableCell call(TableColumn p) { 
         return new TextFieldTableCell(new StringConverter() { 
          @Override 
          public String toString(Object t) { 
           return t.toString(); 
          } 
          @Override 
          public Object fromString(String string) { 
           return string; 
          }          
         }); 
        } 
     }; 
     firstDataColumn.setCellFactory(cellFactoryForMap); 
     secondDataColumn.setCellFactory(cellFactoryForMap); 

     final VBox vbox = new VBox(); 

     vbox.setSpacing(5); 
     vbox.setPadding(new Insets(10, 0, 0, 10)); 
     vbox.getChildren().addAll(label, table_view); 

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

     stage.setScene(scene); 

     stage.show(); 
    } 

    private ObservableList<Map> generateDataInMap() { 
     int max = 10; 
     ObservableList<Map> allData = FXCollections.observableArrayList(); 
     for (int i = 1; i < max; i++) { 
      Map<String, String> dataRow = new HashMap<>(); 

      String value1 = "A" + i; 
      String value2 = "B" + i; 

      dataRow.put(Column1MapKey, value1); 
      dataRow.put(Column2MapKey, value2); 

      allData.add(dataRow); 
     } 
     return allData; 
    } 
} 

Более подробную информацию можно найти here

+0

Да, я могу привязывать карту напрямую, но элементы данных, которые я добавил после инициализации, не будут отображаться, тот же код будет отображаться, если бы я переключился на ObservableList. – user2196346

+0

Можете ли вы отправить какой-либо код, чтобы лучше понять, как вы используете карту – ItachiUchiha

1

Ответ от ItachiUchiha использования столбцы как ключи и строки как отдельные карты. Если вам нужна одна карта со строками в виде ключей-> значений, вам нужно будет добавить слушателя к карте, которая изменит список при добавлении или удалении. Я сделал что-то подобное здесь. https://stackoverflow.com/a/21339428/2855515

+0

oh есть мой код (начинается с Lobby.java, извините, не знаю, как публиковать здесь): http://stackoverflow.com/questions/ 16941980/заселить-TableView-с-observablemap-JavaFX? LQ = 1 – user2196346

4

Если вы используете ObservableList из ObservableMaps в качестве структуры данных Tableview в

ObservableList<ObservableMap> rowMaps = FXCollections.observableArrayList(); 
tableView.setItems(rowMaps); 

и реализовать свой собственный ObservableMapValueFactory

import javafx.beans.property.ObjectProperty; 
import javafx.beans.property.SimpleObjectProperty; 
import javafx.beans.value.ObservableValue; 
import javafx.collections.MapChangeListener; 
import javafx.collections.ObservableMap; 
import javafx.scene.control.TableColumn; 
import javafx.scene.control.TableColumn.CellDataFeatures; 
import javafx.util.Callback; 

public class ObservableMapValueFactory<V> implements 
     Callback<TableColumn.CellDataFeatures<ObservableMap, V>, ObservableValue<V>> { 

    private final Object key; 

    public ObservableMapValueFactory(Object key) { 
     this.key = key; 
    } 

    @Override 
    public ObservableValue<V> call(CellDataFeatures<ObservableMap, V> features) { 
     final ObservableMap map = features.getValue(); 
     final ObjectProperty<V> property = new SimpleObjectProperty<V>((V) map.get(key)); 
     map.addListener(new MapChangeListener<Object, V>() { 
      public void onChanged(Change<?, ? extends V> change) { 
       if (key.equals(change.getKey())) { 
        property.set((V) map.get(key)); 
       } 
      } 
     }); 
     return property; 
    } 
} 

, а затем установить его в качестве значения ячейки завода для вашей колонки (s)

column.setCellValueFactory(new ObservableMapValueFactory<String>(columnId)); 

все изменения ваши данные отражаются в TableView, даже изменения влияют только на ObservableMaps.

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