【问题标题】:JavaFX How do I change the amount by which ScrollPane scrolls?JavaFX 如何更改 ScrollPane 的滚动量?
【发布时间】:2015-09-23 12:12:11
【问题描述】:

我需要知道如何更改 ScrollPane 对象用于上下移动内容的数量。例如,ScrollBar 有以下两种方法:

scrollBar.setUnitIncrement(10);     
scrollBar.setBlockIncrement(50);  

如何使用ScrollPane 而不是ScrollBar 做同样的事情?

【问题讨论】:

标签: java scroll javafx


【解决方案1】:

有同样的问题,但无法找到答案。终于从 Erik 提供的link 中得到了正确的方法,并根据我的需要进行了调整。

由于 scrollPane 本身没有触发“setOnScroll”事件(可能是因为它在触发之前被消耗),所以我必须在 ScrollPane 的 content 上设置 EventHandler:

scrollPane_Content.setContent(vBox_Content);

    vBox_Content.setOnScroll(new EventHandler<ScrollEvent>() {
        @Override
        public void handle(ScrollEvent event) {
            double deltaY = event.getDeltaY()*6; // *6 to make the scrolling a bit faster
            double width = scrollPane_Content.getContent().getBoundsInLocal().getWidth();
            double vvalue = scrollPane_Content.getVvalue();
            scrollPane_Content.setVvalue(vvalue + -deltaY/width); // deltaY/width to make the scrolling equally fast regardless of the actual width of the component
        }
    });

这样做适用于直接使用滚动条以及使用鼠标滚轮上下滚动。

希望这可以帮助其他正在寻找加快滚动面板滚动速度的人。

【讨论】:

  • 您引用的示例设置为水平滚动而不是垂直滚动。我认为您对宽度所做的事情可能不需要?
  • @DoctorParameter 是的,你需要这个宽度参数,因为这个解决方案已经用于垂直滚动,而不是水平滚动
  • 这会根据内容 width 更改垂直滚动...请参阅我的答案,了解使用内容和滚动窗格 height 之间的差异的解决方案.
【解决方案2】:

在外部样式表中你可以这样做

.scroll-pane .scroll-bar:vertical {
    -fx-unit-increment: 10 ;
    -fx-block-increment: 50 ;
}

.scroll-pane .scroll-bar:horizontal {
    -fx-unit-increment: 5 ;
    -fx-block-increment: 20 ;
}

例如。如果您希望它仅应用于单个滚动窗格,请为滚动窗格提供 id 等。

【讨论】:

  • 非常感谢,这确实改变了单击按钮 {向上,向下箭头} 时滚动条的调整量。但不是鼠标滚轮,有解决办法吗??
  • 适用于 JDK 11。感谢 James!
【解决方案3】:

在 ScrollPane 中更快的垂直滚动:

    final double SPEED = 0.01;
    scrollPane.getContent().setOnScroll(scrollEvent -> {
        double deltaY = scrollEvent.getDeltaY() * SPEED;
        scrollPane.setVvalue(scrollPane.getVvalue() - deltaY);
    });

【讨论】:

    【解决方案4】:

    这通过查看内容和滚动窗格之间的高度差异来修复滚动,以便滚动量相同。

    //Fix scroll pane slow scrolling
    scrollPane.getContent().setOnScroll(scrollEvent -> {
        double deltaY = scrollEvent.getDeltaY();
        double contentHeight = scrollPane.getContent().getBoundsInLocal().getHeight();
        double scrollPaneHeight = scrollPane.getHeight();
        double diff = contentHeight - scrollPaneHeight;
        if (diff < 1) diff = 1;
        double vvalue = scrollPane.getVvalue();
        scrollPane.setVvalue(vvalue + -deltaY/diff);
    });
    

    将差值设置为最小值 1 以防止被零除。

    【讨论】:

      【解决方案5】:

      我想要的是简单的设置,它可以在任何地方工作。由于没有给出好的答案,我自己做了一些研究。也许该解决方案也会对您有所帮助。

      因为我想要平滑滚动,所以我创建了过渡类:

      import javafx.animation.Transition;
      import javafx.util.Duration;
      
      public abstract class SmoothishTransition extends Transition {
          private final double mod;
          private final double delta;
      
          private final static int TRANSITION_DURATION = 200;
      
          public SmoothishTransition(SmoothishTransition old, double delta) {
              setCycleDuration(Duration.millis(TRANSITION_DURATION));
              setCycleCount(0);
              // if the last transition was moving inthe same direction, and is still playing
              // then increment the modifer. This will boost the distance, thus looking faster
              // and seemingly consecutive.
              if (old != null && sameSign(delta, old.delta) && playing(old)) {
                  mod = old.getMod() + 1;
              } else {
                  mod = 1;
              }
              this.delta = delta;
          }
      
          public double getMod() {
              return mod;
          }
      
          @Override
          public void play() {
              super.play();
              // Even with a linear interpolation, startup is visibly slower than the middle.
              // So skip a small bit of the animation to keep up with the speed of prior
              // animation. The value of 10 works and isn't noticeable unless you really pay
              // close attention. This works best on linear but also is decent for others.
              if (getMod() > 1) {
                  jumpTo(getCycleDuration().divide(10));
              }
          }
      
          private static boolean playing(Transition t) {
              return t.getStatus() == Status.RUNNING;
          }
      
          private static boolean sameSign(double d1, double d2) {
              return (d1 > 0 && d2 > 0) || (d1 < 0 && d2 < 0);
          }
      }
      

      然后这个类负责滚动:

      import javafx.animation.Interpolator;
      import javafx.event.EventHandler;
      import javafx.scene.Node;
      import javafx.scene.control.ScrollPane;
      import javafx.scene.input.ScrollEvent;
      
      public class SmoothScroll {
      
          private final static double BASE_MODIFIER = 1;
      
          public SmoothScroll(final ScrollPane scrollPane, final Node node) {
              this(scrollPane, node, 160);
          }
          public SmoothScroll(final ScrollPane scrollPane, final Node node, final double baseChange) {
              node.setOnScroll(new EventHandler<ScrollEvent>() {
                  private SmoothishTransition transition;
      
                  @Override
                  public void handle(ScrollEvent event) {
                      if (scrollPane==null) {
                          return;
                      }
                      double deltaYOrg = event.getDeltaY();
                      if (deltaYOrg==0) {
                          return;
                      }
                      double percents = calculatePercents(deltaYOrg>=0);
      
                      final double startingVValue = scrollPane.getVvalue();
      
                      smoothTransition(
                              startingVValue,
                              getFinalVValue(startingVValue, percents),
                              BASE_MODIFIER * deltaYOrg
                      );
                  }
      
                  private void smoothTransition(double startingVValue, double finalVValue, double deltaY) {
                      Interpolator interp = Interpolator.LINEAR;
                      transition = new SmoothishTransition(transition, deltaY) {
                          @Override
                          protected void interpolate(double frac) {
                              scrollPane.setVvalue(
                                      interp.interpolate(startingVValue, finalVValue, frac)
                              );
                          }
                      };
                      transition.play();
                  }
      
                  private double getFinalVValue(double startingVValue, double percents) {
                      double finalVValueToSet = startingVValue + percents;
                      if (finalVValueToSet>1) {
                          return 1d;
                      }
                      if (finalVValueToSet<0) {
                          return 0d;
                      }
                      return finalVValueToSet;
                  }
      
                  private double calculatePercents(boolean positive) {
                      double fullHeight = scrollPane.getContent().getBoundsInLocal().getHeight();
                      double viewableHeight = scrollPane.getBoundsInLocal().getHeight();
                      double fullChangeInHeight = fullHeight-viewableHeight;
                      double percents = baseChange /fullChangeInHeight;
                      if (positive) {
                          percents = percents*-1;
                      }
                      return percents;
                  }
              });
          }
      }
      

      及用法:

      new SmoothScroll(mainScroll, mainVbox);
      

      new SmoothScroll(mainScroll, mainVbox, 50);
      

      此代码应该可以帮助您入门。

      【讨论】:

        【解决方案6】:

        你可以用这个:

        scrollPane.getVerticalScrollBar().setUnitIncrement(20);
        

        【讨论】:

        • 谢谢回复,那个方法不存在,你说的是JavaFX ScrollPane,因为那个是类,没有这个方法。我在这里错过了什么吗???
        • 啊,我的错。我错过了javafx标签,我以为是Swing!
        • 你看到这条评论了吗:stackoverflow.com/questions/17687188/…
        • 所以这不是一个答案,是吗 ;) 你可以考虑删除它..
        猜你喜欢
        • 1970-01-01
        • 2014-11-26
        • 1970-01-01
        • 2021-05-04
        • 1970-01-01
        • 2017-01-18
        • 2016-11-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多