【问题标题】:JavaFX Smooth Scrolling for ListViewListView 的 JavaFX 平滑滚动
【发布时间】:2016-05-06 01:18:09
【问题描述】:

我想知道是否有办法调整 JavaFX 的 ListView 的滚动。

你可能会说它太迟钝了,因为我的集合太大和/或我的CellFactory 太重......只是帧速率似乎太低,即使是少量字符串......

所以我想知道某处是否有设置或指导方针来实现平滑滚动。

提前谢谢你

【问题讨论】:

    标签: java listview optimization javafx smooth-scrolling


    【解决方案1】:

    这是JFoenix's smooth scrolling created for ScrollPanes,但对 ListViews 稍作修改(也适用于 JFoenix 的 JFXListView)

    public class JFXSmoothScroll  {
    
    
    
    private static ScrollBar getScrollbarComponent(ListView<?> control, Orientation orientation) {
        Node n = control.lookup(".scroll-bar");
        if (n instanceof ScrollBar) {
            final ScrollBar bar = (ScrollBar) n;
            if (bar.getOrientation().equals(orientation)) {
                return bar;
            }
        }
    
        return null;
    }   
    
    public static void smoothScrollingListView(ListView<?> listView, double speed) {
        smoothScrollingListView(listView, speed, Orientation.VERTICAL, bounds -> bounds.getHeight());
    }
    
    public static void smoothHScrollingListView(ListView<?> listView, double speed) {
        smoothScrollingListView(listView, speed, Orientation.HORIZONTAL, bounds -> bounds.getHeight());
    }
    
    private  static void smoothScrollingListView(ListView<?> listView, double speed, Orientation orientation, Function<Bounds, Double> sizeFunc) {
        ScrollBar scrollBar = getScrollbarComponent(listView, orientation);
        if (scrollBar == null) {
            return;
        }
        scrollBar.setUnitIncrement(5);
        final double[] frictions = {0.99, 0.1, 0.05, 0.04, 0.03, 0.02, 0.01, 0.04, 0.01, 0.008, 0.008, 0.008, 0.008, 0.0006, 0.0005, 0.00003, 0.00001};
        final double[] pushes = {speed};
        final double[] derivatives = new double[frictions.length];
        final double[] lastVPos = {0};
        Timeline timeline = new Timeline();
        final EventHandler<MouseEvent> dragHandler = event -> timeline.stop();
        final EventHandler<ScrollEvent> scrollHandler = event -> {
            scrollBar.valueProperty().set(lastVPos[0]);
            if (event.getEventType() == ScrollEvent.SCROLL) {
                double direction = event.getDeltaY() > 0 ? -1 : 1;
                for (int i = 0; i < pushes.length; i++) {
                    derivatives[i] += direction * pushes[i];
                }
                if (timeline.getStatus() == Animation.Status.STOPPED) {
                    timeline.play();
                }
    
            }
            event.consume();
        };
        if (scrollBar.getParent() != null) {
            scrollBar.getParent().addEventHandler(MouseEvent.DRAG_DETECTED, dragHandler);
            scrollBar.getParent().addEventHandler(ScrollEvent.ANY, scrollHandler);
        }
        scrollBar.parentProperty().addListener((o,oldVal, newVal)->{
            if (oldVal != null) {
                oldVal.removeEventHandler(MouseEvent.DRAG_DETECTED, dragHandler);
                oldVal.removeEventHandler(ScrollEvent.ANY, scrollHandler);
            }
            if (newVal != null) {
                newVal.addEventHandler(MouseEvent.DRAG_DETECTED, dragHandler);
                newVal.addEventHandler(ScrollEvent.ANY, scrollHandler);
            }
        });
    
        timeline.getKeyFrames().add(new KeyFrame(Duration.millis(3), (event) -> {
            for (int i = 0; i < derivatives.length; i++) {
                derivatives[i] *= frictions[i];
            }
            for (int i = 1; i < derivatives.length; i++) {
                derivatives[i] += derivatives[i - 1];
            }
            double dy = derivatives[derivatives.length - 1];
            double size = sizeFunc.apply(scrollBar.getLayoutBounds());
            scrollBar.valueProperty().set(Math.min(Math.max(scrollBar.getValue() + dy / size, 0), 1));
            lastVPos[0] = scrollBar.getValue();
            if (Math.abs(dy) < 1) {
                if (Math.abs(dy) < 0.001) {
                    timeline.stop();
                } 
            } 
        }));
        timeline.setCycleCount(Animation.INDEFINITE);       
    }
    
    }
    

    这有点老套

    final double[] lastVPos = {0};
    

    因为由于某种原因,在触发 ScrollEvent 之前我找不到触发器并在此之前设置初始滚动值。 方法需要在第一次初始化列表后调用,否则找不到滚动条

    【讨论】:

      猜你喜欢
      • 2018-12-30
      • 2017-03-12
      • 2014-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-19
      • 2011-09-11
      • 1970-01-01
      相关资源
      最近更新 更多