TableView:滚动到达表的底部/顶部时得到通知

时间:2018-12-31 20:33:47

标签: java javafx tableview

我可以听滚动事件:

tableView.addEventFilter(javafx.scene.input.ScrollEvent.SCROLL,
        new EventHandler<javafx.scene.input.ScrollEvent>() {
            @Override
            public void handle(final javafx.scene.input.ScrollEvent scrollEvent) {
            System.out.println("Scrolled.");

            }
        });

但是如果到达表格的底部/顶部,如何通知我?

3 个答案:

答案 0 :(得分:2)

如果您使用的是Java 10+,则可以继承TableViewSkin的子类并访问VirtualFlow。后者具有position属性,您可以使用该属性来确定是否达到顶部或底部。

以下是使用自定义事件的示例:

MyEvent.java

import javafx.event.Event;
import javafx.event.EventType;

public class MyEvent extends Event {

  public static final EventType<MyEvent> ANY = new EventType<>(Event.ANY, "MY_EVENT");
  public static final EventType<MyEvent> TOP_REACHED = new EventType<>(ANY, "TOP_REACHED");
  public static final EventType<MyEvent> BOTTOM_REACHED = new EventType<>(ANY, "BOTTOM_REACHED");

  public MyEvent(EventType<? extends MyEvent> eventType) {
    super(eventType);
  }

}

MyTableViewSkin.java

import javafx.scene.control.TableView;
import javafx.scene.control.skin.TableViewSkin;

public class MyTableViewSkin<T> extends TableViewSkin<T> {

  public MyTableViewSkin(TableView<T> control) {
    super(control);
    getVirtualFlow().positionProperty().addListener((obs, oldVal, newVal) -> {
      if (newVal.doubleValue() == 0.0) {
        control.fireEvent(new MyEvent(MyEvent.TOP_REACHED));
      } else if (newVal.doubleValue() == 1.0) {
        control.fireEvent(new MyEvent(MyEvent.BOTTOM_REACHED));
      }
    });
  }

}

App.java

import javafx.application.Application;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.stage.Stage;

public class App extends Application {

  @Override
  public void start(Stage primaryStage) {
    var table = new TableView<Integer>();
    for (int i = 0; i < 250; i++) {
      table.getItems().add(i);
    }

    var column = new TableColumn<Integer, Number>("Value");
    column.setCellValueFactory(features -> new SimpleIntegerProperty(features.getValue()));
    table.getColumns().add(column);

    table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
    table.setSkin(new MyTableViewSkin<>(table));
    table.addEventHandler(MyEvent.ANY, event -> System.out.printf("%s%n", event.getEventType()));

    primaryStage.setScene(new Scene(table, 500, 300));
    primaryStage.setTitle("Example");
    primaryStage.show();
  }

}

在此示例中,我手动调用table.setSkin。另一个选择是子类TableView并覆盖createDefaultSkin,这将返回您要使用的皮肤。

答案 1 :(得分:2)

一种简单的方法是使用ScrollBar来检索lookup

ScrollBar tvScrollBar = (ScrollBar) tableView.lookup(".scroll-bar:vertical");

然后,您可以添加一个侦听器以检查其是否到达底部(valueProperty的{​​{1}}用滚动百分比表示,因此ScrollBar是顶部,{ {1}}是底部):

0.0

下面是一个简单的MCVE,演示了如何将它们组合在一起:

1.0

答案 2 :(得分:-1)

tableView.addEventFilter(javafx.scene.input.ScrollEvent.SCROLL,
        new EventHandler<javafx.scene.input.ScrollEvent>() {
            @Override
            public void handle(final javafx.scene.input.ScrollEvent scrollEvent) {

                Object virtualFlow =  ((javafx.scene.control.SkinBase<?>) tableView.getSkin()).getChildren().get(1);
                double position = -1;
                try {
                    position = (double) virtualFlow.getClass().getMethod("getPosition").invoke(virtualFlow);
                } catch (Exception ignored) { }

                if(position == 0.0) {
                    System.out.println("scrolled to top!");
                }
                else if(position == 1.0) {
                    System.out.println("scrolled to bottom!");
                }

            }
        });