代码之家  ›  专栏  ›  技术社区  ›  kerner1000

表格视图:滚动到表格底部/顶部时得到通知

  •  0
  • kerner1000  · 技术社区  · 6 年前

    我可以听滚动事件:

    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 回复  |  直到 6 年前
        1
  •  2
  •   Zephyr    6 年前

    一个简单的方法是检索 ScrollBar 使用A lookup :

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

    然后您可以添加一个监听器来检查它是否到达底部 valueProperty 滚动条 以滚动的百分比表示,所以 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();
        }
    }
    
        2
  •  2
  •   Slaw    6 年前

    如果你使用Java 10 +你可以子类 TableViewSkin 并访问 VirtualFlow . 后一类有 position 属性,可用于确定是否已到达顶部或底部。

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

    MyEndo.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 它返回您想要使用的皮肤。

        3
  •  -1
  •   guleryuz    6 年前
    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!");
                    }
    
                }
            });