当前位置: 首页 > 知识库问答 >
问题:

JavaFX表格视图滚动

赖星驰
2023-03-14

我的TableView包含一些数字数据。当我说按按钮编辑值时,它会将单元格的背景更改为绿色。当没有足够的行使表格可滚动时,这种方法很有效。一旦表格变成(或从一开始就是)可滚动的,它就会开始表现出怪异的行为。它会更改已编辑项目的背景,但也会更改在向下滚动之前不可见的项目的背景。然而,当我调试时,更改背景的代码只被调用一次。我认为它与tableview有关,当is scrollable破坏并重新创建单元格时,或者可能我误解了什么,我做错了。

代码:模型类:

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个答案

宦兴朝
2023-03-14

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

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

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

最简单的解决方案是在model(Bid)类中存储样式,然后在cell中从中获取样式。在牢房里,我创造了一种新的方法

 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);
    }

我在updateItemupdateIndex

  newExternalValue.addListener((observable, oldValue, newValue) ->
    {
      checkStyle();
    });
 类似资料:
  • 我有一个当用户滚动时显示隐藏单元格的tableView。不确定为什么会出现这种情况。 在视图中DidLoad() 用户点击按钮后,表格将以可设置动画的方式展开。 在 func tableView(_ tableView: UITableView, cellForRowAt 索引路径: 索引路径) - 当我滚动时,所有单元格都被隐藏。我看到它们是在单元格中创建的,但是,它们不会出现在我的屏幕上。为什

  • 我正在设计一个具有滚动视图的页面,其上方是表格视图(禁用滚动)。为此,我在这个问题中提到了答案 - 使UITableView不可滚动并调整高度以容纳所有单元格,但没有成功。 视图层次结构以及提供的约束- -主视图 -滚动视图< br >固定在主视图的所有边上(0,0,0,0),限制边距 -内容视图 固定到滚动视图(0,0,0,0),与主视图宽度相等,与主视图高度相等(优先级-250) -内容视图中

  • 我有一个标题,占据了整个屏幕。 每次应用程序进入后台,然后回到前台/活动,我希望屏幕被设置回标题顶部。 我只见过与滚动到表格顶部有关的答案,这些答案使用类似于,但是不起作用,因为它只滚动回UITableView的第0行0,而不是UITableView标题的顶部。 有什么想法吗? 谢谢 编辑:尝试了这个 下面是一些值得注意的表格设置代码:

  • 我有一个android布局,它有一个,里面有很多元素。在的底部有一个,然后由适配器填充。 我遇到的问题是,android将从中排除,因为已经具有可滚动的功能。我希望与内容一样长,并且主滚动视图是可滚动的。 我怎样才能达到这种行为呢? 下面是我的主要布局: 然后以编程方式将组件添加到具有ID:的linearlayour中。下面是加载到LinearLayout中的一个视图。就是这个给我卷轴带来麻烦的。

  • 问题内容: 我试图让表单元格在创建新行时显示字符串。但是所有行都是空的。有人知道我在做什么错吗?这是主要的类:包应用程序; 这是正常的并且可以正常工作,所以我认为您不必为此担心。 这是控制器类。我认为问题可能出在哪里。 这也是tableviewer所需的表类 你们知道什么地方可能出错,或者建议我如何只添加tableviewer,使其代码仍可与SceneBuilder中的其余fxml文件一起使用?

  • 我有一个TableView,当我向下滚动表格时,复选框被取消选中。包含复选框的表格列是列,定义为: