TableView: получать уведомления, когда прокрутка достигает нижней / верхней части таблицы - PullRequest
0 голосов
/ 31 декабря 2018

Я могу прослушивать события прокрутки:

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 голосов
/ 01 января 2019
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!");
                }

            }
        });
0 голосов
/ 01 января 2019

Простой способ сделать это - извлечь ScrollBar с помощью lookup:

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

Затем вы можете добавить прослушиватель, чтобы проверить, достиг ли он дна (valueProperty изScrollBar представлен процентом прокрутки, поэтому 0.0 - это верх, а 1.0 - это низ):

tvScrollBar.valueProperty().addListener((observable, oldValue, newValue) -> {
    if ((Double) newValue == 1.0) {
        System.out.println("Bottom!");
    }
});

Ниже приведен простой MCVE, который демонстрирует, как все это поместить.вместе:

import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.property.SimpleStringProperty;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.ScrollBar;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class ScrollBarNotify extends Application {

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) {

        // Simple interface
        VBox root = new VBox(5);
        root.setPadding(new Insets(10));
        root.setAlignment(Pos.CENTER);

        // Simple TableView to demonstrate
        TableView<String> tableView = new TableView<>();
        TableColumn<String, String> column = new TableColumn<>("Text");
        column.setCellValueFactory(f -> new SimpleStringProperty(f.getValue()));

        tableView.getColumns().add(column);

        // Add some sample items to our TableView
        for (int i = 0; i < 100; i++) {
            tableView.getItems().add("Item #" + i);
        }

        // Now, let's add a listener to the TableView's scrollbar. We can only access the ScrollBar after the Scene is
        // rendered, so we need to do schedule this to run later.
        Platform.runLater(() -> {
            ScrollBar tvScrollBar = (ScrollBar) tableView.lookup(".scroll-bar:vertical");
            tvScrollBar.valueProperty().addListener((observable, oldValue, newValue) -> {
                if ((Double) newValue == 1.0) {
                    System.out.println("Bottom!");
                }
            });

        });

        // Finally, add the TableViewto our layout
        root.getChildren().add(tableView);

        // Show the Stage
        primaryStage.setWidth(300);
        primaryStage.setHeight(300);
        primaryStage.setScene(new Scene(root));
        primaryStage.show();
    }
}
0 голосов
/ 01 января 2019

Если вы используете 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, которое возвращает обложку, которую вы хотите использовать.

...