JavaFX TableView滚动

时间:2017-08-11 11:14:18

标签: java javafx

我的TableView包含一些数字数据。当我按“按钮”编辑值时,它会将单元格的背景更改为绿色。当没有足够的行来使表可滚动时,这很有效。一旦表变为(或从开始)可滚动,它就开始变得怪异。它会更改已编辑项目的背景,但它会在您向下滚动之前看不到它。但是,当我调试时,更改背景的代码只调用一次。我认为当可滚动破坏并重新创建单元格时,它必须对该tableview执行某些操作,或者我可能误解了某些内容并且我做错了。

实施例: 我编辑了第二行。 I've edited second row

当我向下滚动一点点时,这个也有不同的背景。 (他们都有同一时间) This one got edited as well

代码: 型号类:

public class Bid {

  private DoubleProperty value; 
  private BooleanProperty valueChanged;

  public Bid(double val) {
    value = new SimpleDoubleProperty();
    valueChanged = new SimpleBooleanProperty();
    setValue(val);
    value.addListener((observable, old, newVal) -> {
      System.out
          .println(observable.toString() + " changed value from " + old.doubleValue() + " to " + newVal.doubleValue());
      valueChanged.setValue(true);
    });
  }

  public double getValue() {
    return value.get();
  }

  public void setValue(double value) {
    this.value.set(value);
  }

  public DoubleProperty valueProperty() {
    return value;
  }

  public boolean isValueChanged() {
    return valueChanged.get();
  }

  public BooleanProperty valueChangedProperty() {
    return valueChanged;
  }

  public void setValueChanged(boolean valueChanged) {
    this.valueChanged.set(valueChanged);
  }

  @Override
  public String toString() {
    return "Bid{" +
        "value=" + value.getValue() +
        '}';
  }
}

我的手机(当我第一次遇到这个问题时,我认为它是去除部分的风格,但删除它并没有帮助):

public class BidCell extends TextFieldTableCell<Bid, Double> {


  private BooleanProperty newExternalValue;

  public BidCell() {
    super(new StringConverter<Double>() { // converter used for conversion from/to string


      @Override
      public String toString(Double object) {
        return object.toString();
      }

      @Override
      public Double fromString(String string) {
        return Double.valueOf(string);
      }
    });

    newExternalValue = new SimpleBooleanProperty();

    newExternalValue.addListener((observable, oldValue, newValue) ->
    {
      if (newValue) {
        String old = this.getStyle();
        this.setStyle("-fx-background-color: #99ff99");
        System.out.println("Color changed");
        Thread thread = new Thread(new StyleRemover(this, old, newExternalValue));
        thread.setDaemon(true);
        thread.start();
      }
    });
  }


  @Override
  public void updateItem(Double item, boolean empty) {
    super.updateItem(item, empty);
    if (getTableRow() != null) {
      if (getTableRow().getItem() != null) {
        if (item != null && !empty) {

          Bid b = getTableRow().getItem() instanceof Bid ? ((Bid) getTableRow().getItem()) : null;
          if (b != null) {
            if (b.isValueChanged()) {
              System.out.println("Setting newExternalValue to true for cell" + this);
              newExternalValue.setValue(true);
              b.setValueChanged(false);
            }
          }
        }
      }
    }
  }

  class StyleRemover implements Runnable {

    private BidCell cell;
    private String oldStyle;
    BooleanProperty newExternalValue;

    public StyleRemover(BidCell cell, String oldStyle, BooleanProperty newExternalValue) {
      this.cell = cell;
      this.oldStyle = oldStyle;
      this.newExternalValue = newExternalValue;
    }

    @Override
    public void run() {
      try {
        Thread.sleep(3000);
        cell.setStyle(oldStyle);
        newExternalValue.setValue(false);
      }
      catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
  }

网格:

public class Grid {

  private TableView<Bid> view;
  private TableColumn<Bid, Double> bidStringTableColumn;
  ObservableList<Bid> bids;

  public TableView<Bid> getView() {
    return view;
  }

  public Grid() {
    view = new TableView<>(); // create tableview

    bids = FXCollections.observableArrayList(); // fill data for it
    bids.addListener((ListChangeListener<Bid>) c -> {
      c.next();
      if (c.wasAdded()) {
        System.out.println("added new value " + c.getAddedSubList().get(0).toString());
      }
    });
    for (double i = 0; i < 10; i += 0.45) {
      Bid e = new Bid(i);

      bids.add(e);
    }
    view.setItems(bids);
    view.setEditable(true);

    bidStringTableColumn = new TableColumn<>("Bid"); // create column with header text "Bid"
    bidStringTableColumn.setCellValueFactory(param -> param.getValue().valueProperty()
        .asObject()); // value factory for column, determines which property will fill column
    bidStringTableColumn.setCellFactory(e -> new BidCell());

    view.getColumns().add(bidStringTableColumn); // add column to table
  }


  public ObservableList<Bid> getBids() {
    return bids;
  }

编辑:这不仅仅是关于样式,我发现如果我开始编辑那个单元格并向下滚动,那么它也处于编辑模式。一种可能的解决方案可能是以某种方式禁用细胞破坏和重新创建滚动,但我还没有找到一种方法如何做到这一点,我不认为它甚至是可能的。 (我知道这是为了表现,但性能对我们来说并不重要,并且不会有数百万行,最多只有100行)

1 个答案:

答案 0 :(得分:0)

我花了一些时间,但我解决了它。 最重要的是这句话

  

“tableview和listview单元格被重用以呈现不同的行   来源清单的数据。“

这基本上意味着您无法将样式设置为单元格,因为滚动时它用于不同的数据。那是我的错。

最简单的解决方案是将样式存储在模型(Bid)类中,然后在单元格中从那里获取它。 在单元格中制作方法

updateItem

我在updateIndex newExternalValue.addListener((observable, oldValue, newValue) -> { checkStyle(); }); 以及

中进行了调用
sendKeys