JavaFX TableView滚动 [英] JavaFX TableView scrolling

查看:1791
本文介绍了JavaFX TableView滚动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have my TableView that contains some number data. When I let's say edit value by button, it changes background of the cell to green. That works good when there is not enough rows to make table scrollable. Once table becomes (or is from beginning) scrollable, it start act weird. It changes background on edited item but it on one that is not visible until you scroll down as well. However when I debug, code that changes background is called only once. I think it has to do something with that tableview when is scrollable destroys and recreates cells, or maybe I misunderstood something and I'm doing it wrong.

示例:
我编辑了第二行。

Example: I've edited second row.

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

And when I scrolled down just a little bit, this one had different background as well. (they both have it same time)

代码:
模型类:

Code: Model class:

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() +
        '}';
  }
}

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

My cell (when i encoutered this problem for first time i thought it is that style removing part, but removing it doesn't help):

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行)

It is not just about styles, I discovered that if I start editing that cell and scroll down, that one is in editing mode as well. One possible solution might be just somehow disable cells destroying and recreating for scrolling, however I haven't found a way how to do it and I don't think it is even possible. (I know that it is there for performance, but performance is not critical for us and there won't be millions of rows, just around 100 max)

推荐答案

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

It took me some time, but i solved it. The most important thing is this sentence


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

"The tableview and listview cells are reused to render different row data of the source list."

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

That basically means that you can't set style to cell because when you scroll it is used for different data. That was my mistake.

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

Simpliest solution was to store style in model ( Bid ) class and then in cell get it from there. In cell i made method

 public void checkStyle() {
    if (getTableRow().getItem() != null) {
      Bid bid = (Bid) getTableRow().getItem();
      this.setDisabled(bid.isDisabled());
      String style = bid.getStyle();
      if (!this.getStyle().equals(style) && getItem() == bid.getValue()) 
          this.setStyle(style);
    }

我打电话给 updateItem updateIndex 并在

  newExternalValue.addListener((observable, oldValue, newValue) ->
    {
      checkStyle();
    });

这篇关于JavaFX TableView滚动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆