【问题标题】:JavaFX ListView on scroll show滚动显示上的 JavaFX ListView
【发布时间】:2018-08-31 17:27:17
【问题描述】:

我在徘徊,是否有一个属性,我可以附加一个监听器,它代表“当列表视图开始显示滚动条时”的动作?

问题是,我有一个到 ListView 的输出,并且在某些时候 ListView 的滚动条会触发。我想捕获该事件并滚动到底部,以便 ListView 对象的下一个添加将自动滚动到底部。

我知道我可以使用监听器来更改项目,但我想在我决定向上滚动时保留该行为,并且一旦添加项目,它就不会滚动回最后一个位置。

【问题讨论】:

  • 当 ScrollBar 显示您可能正在更改我假设的现有对象的可见性?在这种情况下,您可以监听 ScrollBar 的可见标志。虽然我从未尝试过,所以我不能保证这会奏效,但它可能是一种值得尝试的方法。
  • 是的,但我无法在 ListView 中找到监听此标志的位置。
  • 此标志更改没有现有事件,因此您需要创建自己的事件。您可以查看here 了解自定义事件的介绍。
  • 谢谢!对 JavaFX 还是新手,不知道您可以制作自己的事件。
  • 但是……即使触发自定义事件也需要触发器。 “关注什么”的问题仍然存在。

标签: java listview javafx scrollbar


【解决方案1】:

试试这个:

for (Node node : listView.lookupAll(".scroll-bar")) {
    if (node instanceof ScrollBar) {
        ScrollBar scrollBar = (ScrollBar) node;
        scrollBar.visibleProperty().addListener((observable, oldValue, newValue) -> {
            System.out.println(String.format("%s ScrollBar Visible Property Changed From: %s To: %s", scrollBar.getOrientation(), oldValue, newValue));
        });
    }
}

输出:

VERTICAL ScrollBar Visible 属性从:false 更改为:true

注意:此代码应在您设置ListView中的项目后添加,以避免NullPointerException

【讨论】:

  • 谢谢。 “lookupAll”看起来很有趣。会试一试的。
  • 是的,成功了。由于我的列表是动态的并且不是从一开始就加载的,因此将侦听器附加到项目更改以发现滚动条。谢谢。
【解决方案2】:

也许这可以帮助你:

  private boolean scroll = true;
  private ListView<String> listView = new ListView<>();

  Constructor(){
    outputListView.addEventFilter(ScrollEvent.ANY, (e) ->{ //get every scroll event
      if(e.getTextDeltaY() > 0){ //set Scroll event to false when the user scrolls up
        scroll = false;
      }
    });
  }

  public void addToListView(String s){
    listView.getItems().add(s);
    if(scroll)
        listView.scrollTo(listView.getItems().size() -1 );
  }

在这种情况下,当滚动条显示时,listView 会向下滚动,但当用户向上滚动时,listView 不会再向下滚动,直到用户滚动到 Listview 的底部(这是标准的 listview 行为)

【讨论】:

  • 谢谢,但我只想在显示滚动条时滚动到底部,保留原始滚动行为和挂钩。
  • 有趣。谢谢,我试试看。
【解决方案3】:

就我个人而言,我并不热衷于 CSS 查找方法,因为它对我来说太像 hack(我不喜欢依赖硬编码的属性查找)。

我喜欢做的只是在物理布局树中搜索具有正确方向的滚动条:

    public static Optional<ScrollBar> getScrollbar(Node n, Orientation o) {
        LinkedList<Node> queue = new LinkedList<>();
        queue.add(n);
        
        while(! queue.isEmpty()) {
            n = queue.removeFirst();
            
            if (n instanceof ScrollBar) {
                ScrollBar sb = (ScrollBar)n;
                
                if (sb.getOrientation() == o) {
                    return Optional.of(sb);
                }
            }
            
            if (n instanceof Parent) {
                queue.addAll(((Parent) n).getChildrenUnmodifiable());
            }
        }
        
        return Optional.empty();
    }

例如,如果我将一个浮动按钮锚定到列表视图的右上角,当我的列表视图的布局边界属性发生更改时,我会这样做:

    Optional<ScrollBar> sb = getScrollbar(listView, Orientation.VERTICAL);
        
    if (sb.isPresent() && sb.get().isVisible()) {
        StackPane.setMargin(hoverButton, new Insets(1, sb.get().getWidth(), 0, 0));
    }
    else {
        StackPane.setMargin(hoverButton, new Insets(1, 1, 0, 0));
    }

这将使我的按钮滑过,因此它不会悬停在滚动条上。

【讨论】:

    猜你喜欢
    • 2016-05-06
    • 2014-10-22
    • 2017-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-16
    • 2014-06-08
    • 2017-11-13
    相关资源
    最近更新 更多