Upload page content

You can upload content for the page named below. If you change the page name, you can also upload content for another page. If the page name is empty, we derive the page name from the file name.

File to load page content from
Page name
Comment

Locked History Actions

JavaFx/MakeRowVisible

TableView中の特定行を可視にする

JavaFXは複雑になっているにもかかわらずこんな機能も無い。つまり、テーブル中のある行が可視領域から外れてしまったときに、テーブルをスクロールしてその行が可視領域にきてもらいたい。 scrollTo(int index)という機能もあるが、これでは常に先頭行になってしまうため不自然。

There's no functionality of making the specified row visible in TableView. The following code does it. Of course there's builtin scrollTo(int) method, but that behavior is unnatural. I don't want to use it.

import com.sun.javafx.scene.control.skin.*;

import javafx.scene.control.*;

public class TableRowVisible {

  private TableView<?> tableView;
  
  public TableRowVisible(TableView<?> tableView) {
    this.tableView = tableView;
  }

  @SuppressWarnings("restriction")
  public VisibleRange getVisibleRange() {
    TableViewSkin<?> skin = (TableViewSkin<?>)tableView.getSkin();
    if (skin == null) {
      return new VisibleRange(0, 0);
    }
    VirtualFlow<?> flow = (VirtualFlow<?>)skin.getChildren().get(1);
    int indexFirst;
    int indexLast;
    if (flow != null && flow.getFirstVisibleCellWithinViewPort() != null
        && flow.getLastVisibleCellWithinViewPort() != null) {
      indexFirst = flow.getFirstVisibleCellWithinViewPort().getIndex();
      if (indexFirst >= tableView.getItems().size())
        indexFirst = tableView.getItems().size() - 1;
      indexLast = flow.getLastVisibleCellWithinViewPort().getIndex();
      if (indexLast >= tableView.getItems().size())
        indexLast = tableView.getItems().size() - 1;
    } else {
      indexFirst = 0;
      indexLast = 0;
    }
    return new VisibleRange(indexFirst, indexLast - 1); // indexLast may be "half" visible
  }

  /**
   * Make specified row visible.
   * @param index
   */
  public void makeVisible(int index) {
    VisibleRange range = getVisibleRange();
    if (range.contains(index))
      return;
    if (index < range.start) {
      tableView.scrollTo(index);
      return;
    }

    int newStart = index - range.count();
    tableView.scrollTo(newStart);
  }
  
  static class VisibleRange {
    final int start;
    final int end;

    VisibleRange(int start, int end) {
      this.start = start;
      this.end = end;
    }

    int count() {
      return end - start + 1;
    }

    boolean contains(int index) {
      return start <= index && index <= end;
    }

    @Override
    public String toString() {
      return start + "," + end + "," + count();
    }
  }
}