2014-12-16 4 views
1

У меня есть Tableview<ObservableList<Item>>, который не обновляется при обновлении базовых данных. Благодаря отладке я знаю, что базовый ObservableList<Item>> должным образом обновляется. Я убедился, что все свойства Item видны и в формате myFieldProperty().JavaFX TableView не обновляет UI

Вот мое создание таблицы:

pattern= new TableView<>(mainApp.getItemList()); 

    for (ObservableList<Item> row : pattern.getItems()) { 

     for (int i= pattern.getColumns().size(); i<row.size(); i++){ 
      final int columnIndex = i ; 

      TableColumn<ObservableList<Item>, Color> column = new TableColumn<>(); 

      column.setCellValueFactory(rowData -> 
        rowData.getValue() 
        .get(columnIndex).displayColorProperty()); // the Item for this cell 

      column.setCellFactory(col -> { 
       ItemCell cell = new ItemCell(); 

       cell.setOnMouseEntered(e -> { 
        if (cell.getItem() != null) { 
         @SuppressWarnings("unchecked") 
         ObservableList<Item> stitchRow = 
         (ObservableList<Item>) cell.getTableRow().getItem(); 
         mainApp.getRLController().setItemLabel(itemRow.get(columnIndex).toString()); 
        } 
       }); 

       cell.setOnMouseExited(e -> { 
        mainApp.getRLController().setItemLabel(null); 
       }); 

       cell.setOnMouseClicked((MouseEvent e) -> { 
        Item newItem = mainApp.getTBController().getSelectedItem(); 
        if (e.getButton() == MouseButton.PRIMARY && newItem != null) { 

         ObservableList<Item> itemRow = 
           (ObservableList<Item>) cell.getTableRow().getItem(); 
         itemRow.set(columnIndex, newItem); 
         mainApp.getRLController().setItemLabel(itemRow.get(columnIndex).toString()); 
        } 
       }); 

       return cell; 
       }); 

      column.setMinWidth(7); 
      column.setPrefWidth(7); 
      column.setMaxWidth(7); 
      pattern.getColumns().add(column); 
     } 
    } 
    pattern.setFixedCellSize(7); 
    pattern.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);` 

Код для моего пользовательского Cell Factory:

public class ItemCell extends TableCell<ObservableList<Item>, Color> { 

@Override 
protected void updateItem(Color color, boolean empty) { 
    super.updateItem(color, empty); 

    if (empty || color == null) { 
     setText(null); 
     setStyle(null); 
    } else { 

     int r = (int) (color.getRed() * 255); 
     int g = (int) (color.getGreen() * 255); 
     int b = (int) (color.getBlue() * 255); 

     this.setStyle("-fx-background-color: rgb(" + r + "," + g + "," + b + ");" 
      + "-fx-border-color: black; -fx-table-cell-border-color: black;"); 
    } 
    } 
} 
+0

Как вы изменяете данные? Я издевался над этим, и он работал нормально. –

+0

Через метод cell.setOnMouseClicked(). Я заменяю старый элемент новым элементом, который содержит ObjectProperty , а цвет ячейки не изменяется. –

ответ

0

Основная проблема состоит в том, что объект, который вы изменяете (элемент, который является элементом список, представляющий строку) не является свойством, которое ячейка наблюдает за изменениями (displayColorProperty(), принадлежащим этому элементу). Вам необходимо изменить значение свойства, которое ячейка наблюдает.

три возможных решения:

Если возможно, просто изменить displayColor (и другие данные тоже) элемента, отображаемого в клетке. То есть

  cell.setOnMouseClicked((MouseEvent e) -> { 
       if (e.getButton() == MouseButton.PRIMARY && newItem != null) { 

        ObservableList<Item> itemRow = 
          (ObservableList<Item>) cell.getTableRow().getItem(); 
        Item item = itemRow.get(columnIndex); 
        item.setDisplayColor(...); 
        item.set...(...); 
        // ... 
        mainApp.getRLController().setItemLabel(item.toString()); 
       } 
      }); 

Или замените всю строку:

  cell.setOnMouseClicked((MouseEvent e) -> { 
       Item newItem = mainApp.getTBController().getSelectedItem(); 
       if (e.getButton() == MouseButton.PRIMARY && newItem != null) { 

        ObservableList<Item> itemRow = 
          (ObservableList<Item>) cell.getTableRow().getItem(); 
        ObservableList<Item> newRow = FXCollections.observableArrayList(itemRow); 
        newRow.set(columnIndex, newItem); 
        pattern.getItems().set(cell.getTableRow().getIndex(), newRow); 
        mainApp.getRLController().setItemLabel(newRow.get(columnIndex).toString()); 
       } 
      }); 

В противном случае, вы можете сделать свой стол TableView<ObservableList<ObjectProperty<Item>>>. Это немного сложно, но это не так уж плохо. Таким образом вы можете просто установить значение свойства объекта для вашего нового элемента.

Вот полный пример, используя третий метод:

import javafx.application.Application; 
import javafx.beans.property.ObjectProperty; 
import javafx.beans.property.SimpleObjectProperty; 
import javafx.collections.FXCollections; 
import javafx.collections.ObservableList; 
import javafx.scene.Scene; 
import javafx.scene.control.TableCell; 
import javafx.scene.control.TableColumn; 
import javafx.scene.control.TableView; 
import javafx.scene.layout.BorderPane; 
import javafx.scene.paint.Color; 
import javafx.stage.Stage; 

public class ColorTableExample extends Application { 

    @Override 
    public void start(Stage primaryStage) { 
     TableView<ObservableList<ObjectProperty<Item>>> table = new TableView<>(); 


     int NUM_ROWS = 20 ; 
     int NUM_COLS = 15 ; 

     ObservableList<ObservableList<ObjectProperty<Item>>> data = table.getItems() ; 

     for (int y = 0 ; y < NUM_ROWS; y++) { 

      ObservableList<ObjectProperty<Item>> row = FXCollections.observableArrayList(); 
      data.add(row); 

      double saturation = (1.0 * y)/NUM_ROWS ; 
      for (int x = 0 ; x < NUM_COLS; x++) { 
       double hue = x * 360.0/NUM_COLS ; 

       Color color = Color.hsb(hue, saturation, 1.0); 
       row.add(new SimpleObjectProperty<>(new Item(color))); 
      } 

     } 

     for (ObservableList<ObjectProperty<Item>> row : table.getItems()) { 
      for (int i = table.getColumns().size() ; i < row.size(); i++) { 
       int columnIndex = i ; 
       TableColumn<ObservableList<ObjectProperty<Item>>, Item> column = new TableColumn<>(Integer.toString(i+1)); 
       column.setCellValueFactory(rowData -> rowData.getValue().get(columnIndex)); 
       column.setCellFactory(c -> { 
        TableCell<ObservableList<ObjectProperty<Item>>, Item> cell = new TableCell<ObservableList<ObjectProperty<Item>>, Item>() { 
         @Override 
         public void updateItem(Item item, boolean empty) { 
          super.updateItem(item, empty); 
          if (empty) { 
           setStyle(""); 
          } else { 
           Color color = item.getDisplayColor() ; 
           int r = (int) (color.getRed() * 255) ; 
           int g = (int) (color.getGreen() * 255) ; 
           int b = (int) (color.getBlue() * 255) ; 
           String style = String.format(
             "-fx-background-color: rgb(%d, %d, %d);" 
             + "-fx-border-color: black ;" 
             + "-fx-table-cell-border-color: black ;" 
             ,r, g, b); 
           setStyle(style); 
          } 
         } 
        }; 

        cell.setOnMousePressed(evt -> { 
         if (! cell.isEmpty()) { 
          ObservableList<ObjectProperty<Item>> rowData = (ObservableList<ObjectProperty<Item>>) cell.getTableRow().getItem(); 
          Color currentColor = cell.getItem().getDisplayColor(); 
          double newHue = (currentColor.getHue() + 15) % 360 ; 
          Color newColor = Color.hsb(newHue, currentColor.getSaturation(), currentColor.getBrightness()); 
          rowData.get(columnIndex).set(new Item(newColor)); 
         } 
        }); 

        return cell ; 
       }); 
       table.getColumns().add(column); 
      } 
     } 

     BorderPane root = new BorderPane(table, null, null, null, null); 
     primaryStage.setScene(new Scene(root, 600, 400)); 
     primaryStage.show(); 
    } 

    public static class Item { 
     private final ObjectProperty<Color> displayColor = new SimpleObjectProperty<>() ; 

     public Item(Color color) { 
      this.displayColorProperty().set(color); 
     } 

     public final ObjectProperty<Color> displayColorProperty() { 
      return this.displayColor; 
     } 

     public final javafx.scene.paint.Color getDisplayColor() { 
      return this.displayColorProperty().get(); 
     } 

     public final void setDisplayColor(final javafx.scene.paint.Color displayColor) { 
      this.displayColorProperty().set(displayColor); 
     } 


    } 

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

(В какой-то момент, возможно, было бы легче реорганизовать все, чтобы у вас есть реальный класс, представляющий каждую строку в таблице, вместо использования список.)

Также может быть умное обходное решение, использующее экстрактор для списка, но я не мог выполнить эту работу.

+0

Из-за природы данных изменение объекта не является вариантом. Ваша вторая техника работала красиво. Спасибо. –